diff --git a/Loris Toolbox/Scripts/UI/BufferPreview.js b/Loris Toolbox/Scripts/UI/BufferPreview.js index ae79948..0b11c00 100644 --- a/Loris Toolbox/Scripts/UI/BufferPreview.js +++ b/Loris Toolbox/Scripts/UI/BufferPreview.js @@ -117,7 +117,7 @@ inline function rebuild(panel) inline function make(name) { - const var p = Content.getComponent("PreviewPanel"); + local p = Content.getComponent("PreviewPanel"); p.data.paths = []; p.data.channels = []; @@ -131,6 +131,7 @@ inline function make(name) if(event.clicked) { + Engine.playBuffer(this.data.channels, function[this](isPlaying, pos) { this.data.previewPos = pos; @@ -158,15 +159,15 @@ inline function make(name) g.drawRect(b, 1); - for(p in this.data.paths) + for(tp in this.data.paths) { var pb = Rect.removeFromTop(b, this.get("height") / this.data.paths.length); g.setColour(Colours.withAlpha(this.get("itemColour"), 0.1)); - g.fillPath(p, pb); + g.fillPath(tp, pb); g.setColour(0x5aFFFFFF); - g.drawPath(p, pb, 1.0); + g.drawPath(tp, pb, 1.0); } if(this.data.isPlaying) diff --git a/Loris Toolbox/project_info.xml b/Loris Toolbox/project_info.xml index 710ddd6..3f27b8d 100644 --- a/Loris Toolbox/project_info.xml +++ b/Loris Toolbox/project_info.xml @@ -12,8 +12,8 @@ - - + + @@ -36,4 +36,9 @@ + + + + + diff --git a/README.md b/README.md index 4c7ad45..c554931 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,7 @@ # loris-tools -[![Loris Library Build](https://github.com/christophhart/loris-tools/actions/workflows/build_library.yml/badge.svg)](https://github.com/christophhart/loris-tools/actions/workflows/build_library.yml) - A collection of sample analysis tools for HISE based on the Loris library. The [Loris library](http://www.cerlsoundgroup.org/Loris/) allows you resynthesize and morph audio data and is a pretty powerful tool. This repository contains the integration of Loris into [HISE](https://github.com/christophhart/HISE/)! The integration features: -- a prebuild dynamic library (currently only macOS, but Windows & Linux will follow soon) - a scripting API to control loris functions using more or less the same API as the command line interface. - integration into all file management tools in HISE: audio file loading, script Buffer support etc. @@ -18,7 +15,7 @@ A HISE Project that demonstrates how to use the Loris library with the scripting ## loris_library -A dynamic library wrapper that encapsulated the calls into Loris through a C-only API interface. If you want to use Loris in HISE, just grab the latest build and put it in the HISE app data directory. +MOVED into hi_loris module ## loris_test diff --git a/build_library.bat b/build_library.bat deleted file mode 100644 index c263589..0000000 --- a/build_library.bat +++ /dev/null @@ -1,30 +0,0 @@ -@echo off -echo Build Loris Library Windows -git describe --abbrev=0 > tmpFile - -SET /p versionPoint= < tmpFile - -echo Version %versionPoint% - -set projucer="C:\actions-runner\_work\HISE\HISE\tools\projucer\Projucer.exe" -set zip_app="C:\Program Files\7-Zip\7z.exe" -set compiler="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MsBuild.exe" - -%projucer% --resave "loris_library/loris_library.jucer" - -set dll_project=loris_library/Builds/VisualStudio2017/loris_library.sln - -echo Build Debug Configuration... - -%compiler% %dll_project% /t:Build /p:Configuration="Debug";Platform=x64 /v:m - -echo Build Release Configuration... - -%compiler% %dll_project% /t:Build /p:Configuration="Release";Platform=x64 /v:m - -echo Zipping Archive - -%zip_app% a "loris_library_win64.zip" ".\loris_library\Builds\VisualStudio2017\x64\Debug\Dynamic Library\loris_library_debug.dll" -%zip_app% a "loris_library_win64.zip" ".\loris_library\Builds\VisualStudio2017\x64\Release\Dynamic Library\loris_library_release.dll" - -pause \ No newline at end of file diff --git a/build_library.sh b/build_library.sh deleted file mode 100644 index 4a11943..0000000 --- a/build_library.sh +++ /dev/null @@ -1,26 +0,0 @@ -echo loris_library Build Script -echo ============================================================== -echo Cleanup... - -rm -rf loris_library/Builds -rm loris_library_macOS.zip - -export loris_version=$(git describe --tags --abbrev=0) -echo Library version is $loris_version - -chmod +x "/Applications/Projucer.app/Contents/MacOS/Projucer" - -"/Applications/Projucer.app/Contents/MacOS/Projucer" --resave "loris_library/loris_library.jucer" - -set -o pipefail -echo Compiling Loris Dynamic Library... - -echo Compile Debug Configuration -xcodebuild -project ./loris_library/Builds/MacOSX/loris_library.xcodeproj -configuration "Debug" -jobs "6" | xcpretty - -echo Compile Release Configuration... - -xcodebuild -project ./loris_library/Builds/MacOSX/loris_library.xcodeproj -configuration "Release" -jobs "6" | xcpretty - -echo Creating Archive... -zip -X -j loris_library_macOS.zip ./loris_library/Builds/MacOSX/build/Debug/loris_library_debug.dylib ./loris_library/Builds/MacOSX/build/Release/loris_library_release.dylib \ No newline at end of file diff --git a/loris_library/Readme.md b/loris_library/Readme.md new file mode 100644 index 0000000..a576e3a --- /dev/null +++ b/loris_library/Readme.md @@ -0,0 +1,4 @@ +The Loris library was removed with HISE 4.0.0 and is now part of HISE. Just compile HISE with HISE_INCLUDE_LORIS enabled. + +If you want to use Loris in a compiled plugin, enable the Project setting `IncludeLorisInFrontend` + diff --git a/loris_library/Source/Helpers.cpp b/loris_library/Source/Helpers.cpp deleted file mode 100644 index ff9ea0e..0000000 --- a/loris_library/Source/Helpers.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This file is part of the HISE loris_library codebase (https://github.com/christophhart/loris-tools). - * Copyright (c) 2023 Christoph Hart - * - * 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, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "Helpers.h" -#include "LorisState.h" - - -namespace loris2hise -{ - -juce::var Options::toJSON() const -{ - juce::DynamicObject::Ptr obj = new juce::DynamicObject(); - - obj->setProperty(OptionIds::timedomain, - getTimeDomainOptions()[(int)currentDomainType]); - - obj->setProperty(OptionIds::freqfloor, freqfloor); - obj->setProperty(OptionIds::ampfloor, ampfloor); - obj->setProperty(OptionIds::sidelobes, sidelobes); - obj->setProperty(OptionIds::freqdrift, freqdrift); - obj->setProperty(OptionIds::hoptime, hoptime); - obj->setProperty(OptionIds::croptime, croptime); - obj->setProperty(OptionIds::bwregionwidth, bwregionwidth); - obj->setProperty(OptionIds::windowwidth, windowwidth); - obj->setProperty(OptionIds::enablecache, enablecache); - - return juce::var(obj.get()); -} - -juce::StringArray Options::getTimeDomainOptions() -{ - static const juce::StringArray options = - { - "seconds", - "samples", - "0to1" - }; - - return options; -} - -void Options::initLorisParameters() -{ - //hoptime = analyzer_getHopTime(); - //croptime = analyzer_getCropTime(); - freqfloor = analyzer_getFreqFloor(); - ampfloor = analyzer_getAmpFloor(); - sidelobes = analyzer_getSidelobeLevel(); - bwregionwidth = analyzer_getBwRegionWidth(); - windowwidth = 1.0; - enablecache = false; -} - -bool Options::update(const juce::Identifier& id, const juce::var& value) -{ - if (id == OptionIds::timedomain) - { - auto x = value.toString().trim().unquoted(); - - auto idx = getTimeDomainOptions().indexOf(x); - - if (idx == -1) - throw juce::Result::fail("unknown time domain option: " + value.toString()); - - currentDomainType = (TimeDomainType)idx; - - return true; - } - - if (id == OptionIds::freqfloor) { freqfloor = (double)value; if(initialised) analyzer_setFreqFloor(freqfloor); return true; } - if (id == OptionIds::ampfloor) { ampfloor = (double)value; if (initialised) analyzer_setAmpFloor(ampfloor); return true; } - if (id == OptionIds::sidelobes) { sidelobes = (double)value; if (initialised) analyzer_setSidelobeLevel(sidelobes); return true; } - if (id == OptionIds::freqdrift) { freqdrift = (double)value; - return true; } - if (id == OptionIds::hoptime) { hoptime = (double)value; if (initialised) analyzer_setHopTime(hoptime); return true; } - if (id == OptionIds::croptime) { croptime = (double)value; if (initialised) analyzer_setCropTime(croptime); return true; } - if (id == OptionIds::bwregionwidth) { bwregionwidth = (double)value; if (initialised) analyzer_setBwRegionWidth(bwregionwidth); return true; } - if (id == OptionIds::enablecache) { enablecache = (bool)value; return true; } - if (id == OptionIds::windowwidth) { windowwidth = jlimit(0.125, 4.0, (double)value); return true; } - - throw juce::Result::fail("Invalid option: " + id.toString()); -} - -void Helpers::reportError(const char* msg) -{ - if (LorisState::getCurrentInstance() != nullptr) - LorisState::getCurrentInstance()->reportError(msg); -} - -void Helpers::logMessage(const char* msg) -{ - if (LorisState::getCurrentInstance() != nullptr) - LorisState::getCurrentInstance()->messages.add(juce::String(msg)); -} - -} diff --git a/loris_library/Source/Helpers.h b/loris_library/Source/Helpers.h deleted file mode 100644 index 49e0e32..0000000 --- a/loris_library/Source/Helpers.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * This file is part of the HISE loris_library codebase (https://github.com/christophhart/loris-tools). - * Copyright (c) 2023 Christoph Hart - * - * 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, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - - - - -#include "src/loris.h" - -#include "ThreadController.h" -#include "src/Breakpoint.h" -#include "src/PartialUtils.h" - -#include - -namespace loris2hise -{ -using namespace juce; - - - - -enum class TimeDomainType -{ - Seconds, - Samples, - Normalised, - Frequency, - numTimeDomainTypes -}; - -/** The configuration settings for the LorisState. You can change these using loris_config(). */ -struct Options -{ - /** Creates a JSON version of this object. */ - var toJSON() const; - - /** Returns all options for the timedomain property. Currently: `["seconds", "samples", "0oto1"]`*/ - static StringArray getTimeDomainOptions(); - - /** @internal: init the values. */ - void initLorisParameters(); - - /** updates the configuration of the given property with the value. */ - bool update(const Identifier& id, const var& value); - - /** The timedomain used for all time (x-axis) values. - - By default, loris uses seconds for all time values, but you can change it for more convenient - calculations. The possible options are: - - - "seconds" (default): the time in seconds (not milliseconds!) - - "samples": the time in samples depending on the sample rate of the file - - "0to1": the time in a normalized version from 0.0 (start of file) to 1.0 (end of file). - */ - TimeDomainType currentDomainType = TimeDomainType::Seconds; - - /** The lowest frequency that is considered as harmonic content. */ - double freqfloor = 40.0; - - /** The lowest amplitude that is considered relevant, amplitudes below that value are considered below the noise floor. */ - double ampfloor = 90.0; - - /** The gain of the side lobes of the analysis window. */ - double sidelobes = 90.0; - - /** The max frequency drift that can occur in the sample (in cent). This defines a tolerance of pitch variations. */ - double freqdrift = 50.0; - - /** The time between analysis windows. */ - double hoptime = 0.0129; - - /** the time between I don't know. */ - double croptime = 0.0129; - - /** ??? */ - double bwregionwidth = 1.0; - - /** Enables caching of the input file. If this is true, then analyze calls to previously analyzed files are skipped. */ - bool enablecache = true; - - /** The window width scale factor. */ - double windowwidth = 1.0; - - /** If this is true, it will also call the loris_setXXX methods. */ - bool initialised = false; - - hise::ThreadController* threadController = nullptr; -}; - - - -/** This struct will be used as argument for the custom function. */ -struct CustomFunctionArgs -{ - /** The function pointer type that is passed into loris_process_custom(). */ - using FunctionType = bool(*)(CustomFunctionArgs&); - - /** @internal The function object alias. */ - using Function = std::function; - - /** Creates a function args from the breakpoint, the channel index and the LorisState context. */ - CustomFunctionArgs(void* obj_, const Loris::Breakpoint& b, int channelIndex_, - int partialIndex_, - double sampleRate_, - double time_, - double rootFrequency_) : - channelIndex(channelIndex_), - partialIndex(partialIndex_), - sampleRate(sampleRate_), - rootFrequency(rootFrequency_), - obj(obj_), - time(time_) - { - frequency = b.frequency(); - phase = b.phase(); - gain = b.amplitude(); - bandwidth = b.bandwidth(); - }; - - // Constants ======================================== - - /** The channel in the supplied audio file. */ - int channelIndex = 0; - - /** The index of the partial. */ - int partialIndex = 0; - - /** The sample rate of the file. */ - double sampleRate = 44100.0; - - /** the root frequency that was passed into loris_analyze. */ - double rootFrequency = 0.0; - - /** @internal: a pointer to the state context. */ - void* obj = nullptr; - - // Variable properties ============================== - - /** The time of the breakpoint. The domain depends on the `timedomain` configuration option. */ - double time = 0.0; - - /** The frequency of partial at the breakpoint in Hz. */ - double frequency = 0.0; - - /** The phase of the the partial at the breakpoint in radians (0 ... 2*PI). */ - double phase = 0.0; - - /** The amplitude of the partial. */ - double gain = 1.0; - - /** The "noisiness" of the partial at the given breakpoint. (0.0 = pure sinusoidal, 1.0 = full noise). */ - double bandwidth = 0.0; -}; - -/** @internal Some helper functions. */ -struct Helpers -{ - static void reportError(const char* msg); - - static void logMessage(const char* msg); -}; - -} diff --git a/loris_library/Source/LorisState.cpp b/loris_library/Source/LorisState.cpp deleted file mode 100644 index ef5866f..0000000 --- a/loris_library/Source/LorisState.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * This file is part of the HISE loris_library codebase (https://github.com/christophhart/loris-tools). - * Copyright (c) 2023 Christoph Hart - * - * 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, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "LorisState.h" - -namespace loris2hise { - -LorisState* LorisState::currentInstance = nullptr; - -LorisState::LorisState() : - lastError(juce::Result::ok()) -{ - setExceptionHandler(Helpers::reportError); - setNotifier(Helpers::logMessage); -} - -LorisState::~LorisState() -{ - analysedFiles.clear(); - messages.clear(); -} - -LorisState* LorisState::getCurrentInstance(bool forceCreate /*= false*/) -{ - if (currentInstance == nullptr || forceCreate) - currentInstance = new LorisState(); - - return currentInstance; -} - -void LorisState::resetState(void* state) -{ - if (state != getCurrentInstance()) - currentInstance = (LorisState*)state; - - ((LorisState*)state)->lastError = juce::Result::ok(); -} - -MultichannelPartialList* LorisState::getExisting(const File& f) -{ - for (auto af : analysedFiles) - { - if (af->matches(f)) - return af; - } - - return nullptr; -} - -void LorisState::reportError(const char* msg) -{ - lastError = juce::Result::fail(msg); -} - -bool LorisState::analyse(const juce::File& audioFile, double rootFrequency) -{ - for (const auto& af : analysedFiles) - { - if (af->matches(audioFile)) - { - if (currentOption.enablecache) - { - messages.add("Skip " + audioFile.getFileName()); - return true; - } - else - { - analysedFiles.removeObject(af); - break; - } - } - } - juce::AudioFormatManager m; - m.registerBasicFormats(); - - auto driftFactor = std::pow(2.0, currentOption.freqdrift / 1200.0); - - analyzer_configure(rootFrequency * 0.8, rootFrequency * currentOption.windowwidth, currentOption.threadController); - //analyzer_setWindowWidth(rootFrequency * currentOption.windowwidth); - analyzer_setFreqDrift(rootFrequency * 0.25); - - analyzer_storeNoBandwidth(); - - if (!currentOption.initialised) - { - currentOption.initLorisParameters(); - currentOption.initialised = true; - } - - analyzer_setHopTime(currentOption.hoptime); - analyzer_setCropTime(currentOption.croptime); - - if (juce::ScopedPointer r = m.createReaderFor(audioFile)) - { - messages.add("Analyse " + audioFile.getFileName()); - - auto newEntry = new MultichannelPartialList(audioFile.getFullPathName(), r->numChannels); - - newEntry->setMetadata(r, rootFrequency); - newEntry->setOptions(currentOption); - - juce::AudioSampleBuffer bf(r->numChannels, (int)r->lengthInSamples); - - r->read(&bf, 0, (int)r->lengthInSamples, 0, true, true); - - juce::HeapBlock buffer; - - buffer.allocate(bf.getNumSamples(), true); - - for (int c = 0; c < bf.getNumChannels(); c++) - { - if (auto s = hise::ThreadController::ScopedStepScaler(currentOption.threadController, c, bf.getNumChannels())) - { - if (!s) - return false; - - for (int i = 0; i < bf.getNumSamples(); i++) - buffer[i] = bf.getSample(c, i); - - auto list = newEntry->get(c); - - analyze(buffer, bf.getNumSamples(), r->sampleRate, list); - } - } - - newEntry->saveAsOriginal(); - //newEntry->prepareToMorph(); - - analysedFiles.add(newEntry); - - messages.add("... Analysed OK"); - return true; - } - - return false; -} - -double LorisState::getOption(const juce::Identifier &id) const -{ - juce::String msg; - msg << "Get option " << id; - - Helpers::logMessage(msg.getCharPointer().getAddress()); - - return (double)currentOption.toJSON()[id]; -} - -bool LorisState::setOption(const juce::Identifier& id, const juce::var& data) -{ - juce::String msg; - msg << "Set option " << id << " with value " << data.toString().quoted(); - - Helpers::logMessage(msg.getCharPointer().getAddress()); - - try - { - if (!currentOption.update(id, data)) - return false; - - for (auto& s : analysedFiles) - s->setOptions(currentOption); - } - catch (juce::Result& r) - { - lastError = r; - return false; - } - - msg = "Updated options to: "; - msg << "\n" << juce::JSON::toString(currentOption.toJSON()); - - Helpers::logMessage(msg.getCharPointer().getAddress()); - - return true; -} - - - - -} diff --git a/loris_library/Source/LorisState.h b/loris_library/Source/LorisState.h deleted file mode 100644 index cbea30a..0000000 --- a/loris_library/Source/LorisState.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of the HISE loris_library codebase (https://github.com/christophhart/loris-tools). - * Copyright (c) 2023 Christoph Hart - * - * 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, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "Properties.h" - -#include "Helpers.h" -#include "MultichannelPartialList.h" - -#include "JuceHeader.h" - -namespace loris2hise { -using namespace juce; - -/** A state that holds all information. Create it with createLorisState and delete it with deleteLorisState(). - - This avoids having a global context, however the error reporting will only work with the - state that was created last (because the loris error handling is global). - */ -struct LorisState -{ - LorisState(); - - ~LorisState(); - - static LorisState* getCurrentInstance(bool forceCreate = false); - - static void resetState(void* state); - - void reportError(const char* msg); - - bool analyse(const juce::File& audioFile, double rootFrequency); - - bool setOption(const juce::Identifier& id, const juce::var& data); - - double getOption(const juce::Identifier& id) const; - - MultichannelPartialList* getExisting(const File& f); - - const char* getLastError() const - { - return lastError.getErrorMessage().getCharPointer().getAddress(); - } - - String getLastMessage() - { - if(!messages.isEmpty()) - { - auto lastMessage = messages[messages.size()-1]; - messages.remove(messages.size()-1); - return lastMessage; - } - - return {}; - } - - void setThreadController(hise::ThreadController* tc) - { - currentOption.threadController = tc; - } - -private: - - friend class Helpers; - - Options currentOption; - - juce::Result lastError; - - juce::OwnedArray analysedFiles; - - juce::StringArray messages; - - static LorisState* currentInstance; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LorisState); -}; - -} diff --git a/loris_library/Source/MultichannelPartialList.cpp b/loris_library/Source/MultichannelPartialList.cpp deleted file mode 100644 index a46d10e..0000000 --- a/loris_library/Source/MultichannelPartialList.cpp +++ /dev/null @@ -1,638 +0,0 @@ -/* - * This file is part of the HISE loris_library codebase (https://github.com/christophhart/loris-tools). - * Copyright (c) 2023 Christoph Hart - * - * 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, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "MultichannelPartialList.h" -#include "src/Resampler.h" - -namespace loris2hise { -using namespace juce; - - -MultichannelPartialList::MultichannelPartialList(const juce::String& name, int numChannels) : - filename(name) -{ - for (int i = 0; i < numChannels; i++) - { - list.add(createPartialList()); - } -} - -MultichannelPartialList::~MultichannelPartialList() -{ - for (auto& p : list) - destroyPartialList(p); -} - -double MultichannelPartialList::convertTimeToSeconds(double timeInput) const -{ - if (options.currentDomainType == TimeDomainType::Seconds) - return timeInput; - if (options.currentDomainType == TimeDomainType::Samples) - { - return timeInput / sampleRate; - } - if (options.currentDomainType == TimeDomainType::Normalised) - { - return timeInput * numSamples / sampleRate; - } - if (options.currentDomainType == TimeDomainType::Frequency) - { - return timeInput; - } - - jassertfalse; - return timeInput; -} - -double MultichannelPartialList::convertSecondsToTime(double timeInput) const -{ - if (options.currentDomainType == TimeDomainType::Seconds) - return timeInput; - if (options.currentDomainType == TimeDomainType::Samples) - { - return timeInput * sampleRate; - } - if (options.currentDomainType == TimeDomainType::Normalised) - { - return timeInput * sampleRate / numSamples; - } - if (options.currentDomainType == TimeDomainType::Frequency) - { - return timeInput; - } - - jassertfalse; - return timeInput; -} - -void MultichannelPartialList::setMetadata(juce::AudioFormatReader* r, double root) -{ - numSamples = (int)r->lengthInSamples; - sampleRate = r->sampleRate; - rootFrequency = root; -} - -LinearEnvelope* MultichannelPartialList::createEnvelopeFromJSON(const juce::var& data) -{ - auto env = createLinearEnvelope(); - - auto cleanup = [env]() { destroyLinearEnvelope(env); }; - - checkArgs(data.isArray(), "must be a a list of [x, y] points", cleanup); - - if (data.isArray()) - { - for (const auto& s : *data.getArray()) - { - checkArgs(s.isArray() && - s.size() == 2, "point element must be an array with two elements", cleanup); - - auto timeValue = convertTimeToSeconds(s[0]); - - linearEnvelope_insertBreakpoint(env, timeValue, s[1]); - } - } - - return env; -} - -void MultichannelPartialList::saveAsOriginal() -{ - for (const auto l : list) - { - auto newO = createPartialList(); - partialList_copy(newO, l); - original.add(newO); - } - - jassert(list.size() == original.size()); -} - -void MultichannelPartialList::checkArgs(bool condition, const juce::String& error, const std::function& additionalCleanupFunction /*= {}*/) -{ - if (!condition) - { - if (additionalCleanupFunction) - additionalCleanupFunction(); - - throw juce::Result::fail("process args error: " + error); - } -} - -bool MultichannelPartialList::processCustom(void* obj, const CustomFunctionArgs::Function& f) -{ - int channelIndex = 0; - - for (auto l : list) - { - int partialIndex = 0; - - for (auto& p : *l) - { - for (Partial::iterator iter = p.begin(); iter != p.end(); ++iter) - { - auto t = convertSecondsToTime(iter.time()); - auto& b = iter.breakpoint(); - - CustomFunctionArgs a(obj, b, channelIndex, partialIndex, sampleRate, t, rootFrequency); - - if (f(a)) - return true; - - iter.time(); - breakpoint_setAmplitude(&b, a.gain); - breakpoint_setPhase(&b, a.phase); - breakpoint_setFrequency(&b, a.frequency); - breakpoint_setBandwidth(&b, a.bandwidth); - } - - partialIndex++; - } - - channelIndex++; - } - - return false; -} - - -bool MultichannelPartialList::process(const juce::Identifier& command, const juce::var& data) -{ - juce::String msg; - msg << "Process " << filename << " with command " << command << " and JSON argument " << juce::JSON::toString(data); - - Helpers::logMessage(msg.getCharPointer().getAddress()); - - if (command == ProcessIds::reset) - { - checkArgs(data.isObject() && - data.getDynamicObject()->getProperties().isEmpty(), - "must be an empty object"); - - for (int i = 0; i < list.size(); i++) - { - partialList_clear(list[i]); - partialList_copy(list[i], original[i]); - } - - return true; - } - if (command == ProcessIds::applyFilter) - { - juce::ScopedValueSetter svs(options.currentDomainType, TimeDomainType::Frequency); - - auto env = createEnvelopeFromJSON(data); - - for (auto& l : list) - { - for (auto& p : *l) - { - - for (auto& b : p) - { - auto freq = breakpoint_getFrequency(&b); - auto gain = linearEnvelope_valueAt(env, freq); - - gain *= breakpoint_getAmplitude(&b); - - breakpoint_setAmplitude(&b, gain); - } - } - } - - destroyLinearEnvelope(env); - return true; - } - if (command == ProcessIds::shiftTime) - { - checkArgs(data.hasProperty("offset"), "must be a JSON object with a offset property"); - - auto offset = convertTimeToSeconds(data["offset"]); - - for (auto l : list) - shiftTime(l, offset); - - return true; - } - if (command == ProcessIds::shiftPitch) - { - if (data.isArray()) - { - auto env = createEnvelopeFromJSON(data); - - for (auto l : list) - shiftPitch(l, env); - - destroyLinearEnvelope(env); - } - else if (data.isObject()) - { - checkArgs(data.hasProperty("offset"), "shiftPitch with a constant value needs a JSON with an offset property"); - - auto s = data["offset"]; - - auto env = createLinearEnvelope(); - - linearEnvelope_insertBreakpoint(env, 0.0, s); - - for (auto l : list) - { - shiftPitch(l, env); - } - - destroyLinearEnvelope(env); - } - - - return true; - } - if (command == ProcessIds::scaleFrequency) - { - auto env = createEnvelopeFromJSON(data); - - for (auto l : list) - scaleFrequency(l, env); - - destroyLinearEnvelope(env); - - return true; - } - - if (command == ProcessIds::dilate) - { - checkArgs(data.isArray(), "must be an array with two list of data points"); - - if (data.isArray()) - { - juce::Array itimes; - juce::Array ttimes; - - auto iv = data[0]; - auto tv = data[1]; - - checkArgs(iv.isArray(), "first element must be a list of numbers"); - checkArgs(tv.isArray(), "second element must be a list of numbers"); - - for (int i = 0; i < iv.size(); i++) - { - checkArgs(iv[i].isDouble(), - "in[" + juce::String(i) + "] must be a double number"); - - checkArgs(tv[i].isDouble(), - "out[" + juce::String(i) + "] must be a double number"); - - itimes.add(convertTimeToSeconds(iv[i])); - ttimes.add(convertTimeToSeconds(tv[i])); - } - - for (auto l : list) - dilate(l, itimes.getRawDataPointer(), ttimes.getRawDataPointer(), itimes.size()); - } - - return true; - } - - throw juce::Result::fail("Invalid command: " + command); -} - -size_t MultichannelPartialList::getRequiredBytes() const -{ - return list.size() * numSamples * sizeof(float); -} - -juce::AudioSampleBuffer MultichannelPartialList::synthesize() -{ - juce::String msg; - msg << "Synthesize " << filename << "..."; - Helpers::logMessage(msg.getCharPointer().getAddress()); - juce::AudioSampleBuffer output(list.size(), numSamples); - - juce::HeapBlock buffer; - buffer.allocate(numSamples, true); - - for (int i = 0; i < list.size(); i++) - { - juce::FloatVectorOperations::clear(buffer, numSamples); - ::synthesize(list[i], buffer, numSamples, sampleRate); - - for (int s = 0; s < numSamples; s++) - { - output.setSample(i, s, (float)buffer[s]); - } - } - - Helpers::logMessage("...Synthesize OK"); - return output; -} - -bool MultichannelPartialList::prepareToMorph(bool removeUnlabeled) -{ - if(preparedForMorph) - return true; - - Helpers::logMessage("Prepare partial list for morphing"); - - if (auto s = hise::ThreadController::ScopedStepScaler(options.threadController, 0, 5)) - { - for (auto p : list) - { - if (auto s2 = hise::ThreadController::ScopedStepScaler(options.threadController, list.indexOf(p), list.size())) - { - auto l = std::pow(2.0, -1.0 * options.freqdrift / 1200.0); - auto h = std::pow(2.0, options.freqdrift / 1200.0); - - LinearEnvelope* env; - - { - hise::ThreadController::ScopedRangeScaler s(options.threadController, 0.0, 0.5); - env = createF0Estimate(p, rootFrequency * l, rootFrequency * h, options.hoptime * 10.0, options.threadController); - } - - - { - hise::ThreadController::ScopedRangeScaler s(options.threadController, 0.5, 1.0); - channelize(p, env, 1); - } - - destroyLinearEnvelope(env); - } - - } - } - - - - if (auto s = hise::ThreadController::ScopedRangeScaler(options.threadController, 0.5, 1.0)) - { - int idx = 0; - int length = list.size(); - - for (auto p : list) - { - if (auto ls = hise::ThreadController::ScopedStepScaler(options.threadController, idx++, length)) - { - hise::ThreadController::ScopedStepScaler(options.threadController, 0, 5); - collate(p); - - if (!options.threadController) - return false; - - hise::ThreadController::ScopedStepScaler(options.threadController, 1, 5); - sortByLabel(p); - - if (!options.threadController) - return false; - - hise::ThreadController::ScopedStepScaler(options.threadController, 2, 5); - sift(p); - - if (!options.threadController) - return false; - - hise::ThreadController::ScopedStepScaler(options.threadController, 3, 5); - distill(p); - - if (!options.threadController) - return false; - - if (removeUnlabeled) - removeLabeled(p, 0); - - if (!options.threadController) - return false; - - hise::ThreadController::ScopedStepScaler(options.threadController, 4, 5); - sortByLabel(p); - - if (!options.threadController) - return false; - - // better to compute this only once: - const double OneOverSrate = 1. / sampleRate; - - // use a Resampler to quantize the Breakpoint times and - // correct the phases: - Loris::Resampler quantizer(options.hoptime); - quantizer.setPhaseCorrect(true); - - for (auto& pr : *p) - { - if (!options.threadController) - return false; - - quantizer.quantize(pr); - } - } - } - - preparedForMorph = true; - return true; - } - else - return false; - -} - -juce::AudioSampleBuffer MultichannelPartialList::renderEnvelope(const juce::Identifier ¶meter, int partialIndex) -{ - AudioSampleBuffer b(getNumChannels(), getNumSamples()); - b.clear(); - - if(parameter == ParameterIds::rootFrequency) - { - for(auto e: rootFrequencyEnvelopes) - destroyLinearEnvelope(e); - - rootFrequencyEnvelopes.clear(); - - int c = 0; - - for(auto pl: list) - { - const var hoptimeSamples = options.hoptime * sampleRate; - - LinearEnvelope* env = createF0Estimate(pl, rootFrequency * (1.0 + options.freqdrift), rootFrequency / (1.0 + options.freqdrift), options.hoptime * 4.0, options.threadController); - - for(int i = 0; i < b.getNumSamples(); i++) - b.setSample(c, i, linearEnvelope_valueAt(env, i / sampleRate) / rootFrequency); - - rootFrequencyEnvelopes.add(env); - c++; - } - } - else - { - prepareToMorph(); - - int c = 0; - for(auto pl: list) - { - bool found = false; - - for(auto p: *pl) - { - if(partialIndex == (p.label() - 1)) - { - found = true; - - const int sampleDelta = options.hoptime * sampleRate; - SmoothedValue ramp; - std::function vf; - - ramp.reset(sampleRate, options.hoptime); - - if(parameter == ParameterIds::phase) - vf = partial_phaseAt; - if(parameter == ParameterIds::frequency) - vf = partial_frequencyAt; - if(parameter == ParameterIds::gain) - vf = partial_amplitudeAt; - if(parameter == ParameterIds::bandwidth) - vf = partial_bandwidthAt; - - for(int i = 0; i < getNumSamples(); i++) - { - if(i % sampleDelta == 0) - { - auto t = (double)i / sampleRate; - ramp.setTargetValue((float)vf(&p, t)); - } - - b.setSample(c, i, ramp.getNextValue()); - } - } - } - - if(!found) - { - String msg; - msg <<"Can't find partial with label " << String(partialIndex); - Helpers::reportError(msg.getCharPointer().getAddress()); - } - } - - c++; - } - - - - return b; -} - -bool MultichannelPartialList::createSnapshot(const juce::Identifier ¶meter, double timeSeconds, double *buffer, int& numChannels, int &numHarmonics) -{ - auto timeToUse = convertTimeToSeconds(timeSeconds); - - numChannels = getNumChannels(); - - if (auto s = hise::ThreadController::ScopedRangeScaler(options.threadController, 0.0, 0.5)) - { - prepareToMorph(true); - } - - hise::ThreadController::ScopedRangeScaler s2(options.threadController, 0.5, 1.0); - - std::function vf; - - if(parameter == ParameterIds::phase) - vf = partial_phaseAt; - if(parameter == ParameterIds::frequency) - vf = partial_frequencyAt; - if(parameter == ParameterIds::gain) - vf = partial_amplitudeAt; - if(parameter == ParameterIds::bandwidth) - vf = partial_bandwidthAt; - - int index = 1; - - int numMaxHarmonics = 0; - - for (auto& pl : list) - { - for (const auto& part : *pl) - { - numMaxHarmonics = jmax(numMaxHarmonics, part.label()-1); - } - } - - FloatVectorOperations::clear(buffer, numMaxHarmonics); - - int channelOffset = 0; - - int idx = 0; - int length = (double)list.size(); - - auto tc = options.threadController; - - for(auto& pl: list) - { - int thisNum = 0; - - if (auto s = hise::ThreadController::ScopedStepScaler(tc, idx++, length)) - { - for (auto& p : *pl) - { - auto labelIndex = p.label() - 1; - - if (tc != nullptr) - tc->setProgress((double)labelIndex / (double)numMaxHarmonics); - - jassert(isPositiveAndBelow(labelIndex, numMaxHarmonics + 1)); - buffer[channelOffset + labelIndex] = vf(&p, timeToUse); - } - - channelOffset += numMaxHarmonics; - } - else - return false; - } - - numHarmonics = numMaxHarmonics; - - return true; -} - -bool MultichannelPartialList::matches(const juce::File& f) const -{ - return f.getFullPathName() == filename; -} - -int MultichannelPartialList::getNumSamples() const -{ - return numSamples; -} - -int MultichannelPartialList::getNumChannels() const -{ - return list.size(); -} - -void MultichannelPartialList::setOptions(const Options& newOptions) -{ - options = newOptions; -} - - - - - - - - - - -} diff --git a/loris_library/Source/MultichannelPartialList.h b/loris_library/Source/MultichannelPartialList.h deleted file mode 100644 index f63b06c..0000000 --- a/loris_library/Source/MultichannelPartialList.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * This file is part of the HISE loris_library codebase (https://github.com/christophhart/loris-tools). - * Copyright (c) 2023 Christoph Hart - * - * 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, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "src/loris.h" -#include "src/Partial.h" - -#include "Properties.h" -#include "Helpers.h" - -#pragma once - -namespace loris2hise { -using namespace juce; - -/** This object contains a Loris::PartialList for each audio channel. */ -struct MultichannelPartialList -{ - /** @internal only used internally. */ - MultichannelPartialList(const juce::String& name, int numChannels); - - /** @internal only used internally. */ - ~MultichannelPartialList(); - - /** @internal only used internally. */ - double convertTimeToSeconds(double timeInput) const; - - /** @internal only used internally. */ - double convertSecondsToTime(double timeInput) const; - - /** @internal only used internally. */ - PartialList* get(int index) { return list[index]; } - - /** @internal only used internally. */ - void setMetadata(juce::AudioFormatReader* r, double root); - - /** @internal This function creates a linear envelope from points supplied as JSON object. - - The JSON format is a two-dimensional array with `[x, y]` items. - - @example: `[ [0.0, 0.0], [0.5, 0.25], [1.0, 1.0] ]` - - This is used by multiple process algorithm that require a time-varying parameter. Note that the `x` - parameter (=time) is always converted using the global timedomain setting. - */ - LinearEnvelope* createEnvelopeFromJSON(const juce::var& data); - - /** @internal: argument sanitizer. Throws a juce::Result with the supplied error message. */ - void checkArgs(bool condition, const juce::String& error, const std::function& additionalCleanupFunction = {}); - - /** Iterates all channels, partials and breakpoints (3D!) and calls the given function for each data point. - - - state: the LorisState context. This is only used internally. - - f: a function with a single argument that contains a reference to the CustomFunctionArgs object that holds the data - for the breakpoint that should be modified. If the function returns true, the iteration will be aborted. - - returns true if the processing was sucessful and false if there was an error. - */ - bool processCustom(void* obj, const CustomFunctionArgs::Function& f); - - /** Processes the partials of each channel with a predefined function. - - - command: the function you want to execute (see below) - - args: a JSON object containing the data parameters for the algorithm. - - returns true if the processing was sucessful and false if there was an error. - - The list of available process commands is defined in the ProcessIds namespace. - - The JSON data for each command: - - - reset: an empty object `{}` - - - - */ - bool process(const juce::Identifier& command, const juce::var& args); - - bool createSnapshot(const juce::Identifier& id, double timeSeconds, double* buffer, int& numChannels, int& numHarmonics); - - juce::AudioSampleBuffer synthesize(); - - juce::AudioSampleBuffer renderEnvelope(const Identifier& parameter, int partialIndex); - - bool matches(const juce::File& f) const; - - size_t getRequiredBytes() const; - int getNumSamples() const; - int getNumChannels() const; - - /**@ internal **/ - void setOptions(const Options& newOptions); - - /** @internal */ - void saveAsOriginal(); - - bool prepareToMorph(bool removeUnlabeled=false); - -private: - - bool preparedForMorph = false; - - Options options; - - juce::String filename; - - int numSamples = 0; - double sampleRate = 0.0; - double rootFrequency; - - juce::Array list; - - juce::Array rootFrequencyEnvelopes; - - juce::Array original; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MultichannelPartialList); -}; - -} diff --git a/loris_library/Source/Properties.h b/loris_library/Source/Properties.h deleted file mode 100644 index 1b1085a..0000000 --- a/loris_library/Source/Properties.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This file is part of the HISE loris_library codebase (https://github.com/christophhart/loris-tools). - * Copyright (c) 2023 Christoph Hart - * - * 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, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "JuceHeader.h" - -namespace loris2hise -{ - -#define DECLARE_ID(x) static const juce::Identifier x(#x); - -namespace OptionIds -{ - DECLARE_ID(timedomain); - DECLARE_ID(enablecache); - DECLARE_ID(windowwidth); - DECLARE_ID(freqfloor); - DECLARE_ID(ampfloor); - DECLARE_ID(sidelobes); - DECLARE_ID(freqdrift); - DECLARE_ID(hoptime); - DECLARE_ID(croptime); - DECLARE_ID(bwregionwidth); - - /** @internal */ - static juce::Array getAllIds() - { - return { timedomain, enablecache, windowwidth, freqfloor, ampfloor, sidelobes, freqdrift, hoptime, croptime, bwregionwidth }; - }; -} - -namespace ParameterIds -{ - DECLARE_ID(rootFrequency); - DECLARE_ID(frequency); - DECLARE_ID(phase); - DECLARE_ID(gain); - DECLARE_ID(bandwidth); - - static juce::Array getAllIds() - { - return { rootFrequency, frequency, phase, gain, bandwidth }; - }; -}; - -/** This contains a list of all available commands that can be passed into process. */ -namespace ProcessIds -{ - /** Resets the partials to the original. Use this if you have cached the file and want*/ - DECLARE_ID(reset); - DECLARE_ID(shiftTime); - DECLARE_ID(shiftPitch); - DECLARE_ID(applyFilter); - DECLARE_ID(scaleFrequency); - DECLARE_ID(dilate); - DECLARE_ID(custom); - - /** @internal */ - static juce::Array getAllIds() - { - return { reset, shiftTime, shiftPitch, scaleFrequency, dilate, applyFilter, custom }; - } - -} - -#undef DECLARE_ID - -} diff --git a/loris_library/Source/ThreadController.h b/loris_library/Source/ThreadController.h deleted file mode 100644 index d03c832..0000000 --- a/loris_library/Source/ThreadController.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * This file is part of the HISE loris_library codebase (https://github.com/christophhart/loris-tools). - * Copyright (c) 2023 Christoph Hart - * - * 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, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include - -namespace hise -{ - using namespace juce; - - /** A minimal POD that can be used to check the thread state across DLL boundaries. */ - class ThreadController : public ReferenceCountedObject - { - struct Scaler - { - Scaler(bool isStep_ = false) : - isStep(isStep_) - {} - - double getScaledProgress(double input) const - { - if (isStep) - return (v1 + input) / v2; - else - return v1 + (v2 - v1) * input; - } - - bool isStep = false; - double v1 = 0.0; - double v2 = 0.0; - }; - - template struct ScopedScaler - { - template ScopedScaler(ThreadController* parent_, T v1, T v2) : parent(parent_) - { - Scaler s(IsStep); - s.v1 = (double)v1; - s.v2 = (double)v2; - - if (parent != nullptr) - parent->pushProgressScaler(s); - }; - - ~ScopedScaler() - { - if (parent != nullptr) - parent->popProgressScaler(); - }; - - operator bool() const { return parent; } - ThreadController* parent; - }; - - public: - - using Ptr = ReferenceCountedObjectPtr; - using ScopedRangeScaler = ScopedScaler; - using ScopedStepScaler = ScopedScaler; - - ThreadController(Thread* t, double* p, int timeoutMs, uint32& lastTime_) : - juceThreadPointer(t), - progress(p), - timeout(timeoutMs), - lastTime(&lastTime_) - {}; - - ThreadController() : - juceThreadPointer(nullptr), - progress(nullptr), - lastTime(nullptr) - {}; - - operator bool() const - { - if (juceThreadPointer == nullptr) - return false; - - auto thisTime = Time::getMillisecondCounter(); - - if (lastTime != nullptr && *lastTime != 0 && thisTime - *lastTime > timeout) - { - // If this hits, it means that the timeout you've set is too low. - // Either increase the timeout or add more checks in between... - int x = 5; - - // prevent the jassert above to mess up subsequent timeouts... - thisTime = Time::getMillisecondCounter(); - } - - if (lastTime != nullptr) - *lastTime = thisTime; - - return !static_cast(juceThreadPointer)->threadShouldExit(); - } - - /** Allow a bigger time between calls. */ - void extendTimeout(uint32 milliSeconds) - { - if (lastTime != nullptr) - *lastTime += milliSeconds; - } - - - /** Set a progress. If you want to add a scaler to the progress (for indicating a subprocess, use either ScopedStepScaler or ScopedRangeScalers). */ - bool setProgress(double p) - { - if (progress == nullptr) - return true; - - for (int i = progressScalerIndex-1; i >= 0; i--) - { - p = jlimit(0.0, 1.0, progressScalers[i].getScaledProgress(p)); - } - - // If this hits, you might have forgot a scaler in the call stack... - jassert(*progress <= p); - - *progress = p; - - return *this; - } - - private: - - static constexpr int NumProgressScalers = 32; - - void pushProgressScaler(const Scaler& f) - { - progressScalers[progressScalerIndex++] = f; - jassert(isPositiveAndBelow(progressScalerIndex, NumProgressScalers)); - setProgress(0.0); - } - - void popProgressScaler() - { - progressScalers[progressScalerIndex--] = {}; - jassert(progressScalerIndex >= 0); - } - - void* juceThreadPointer = nullptr; - double* progress = nullptr; - mutable uint32* lastTime = nullptr; - uint32 timeout = 0; - int progressScalerIndex = 0; - Scaler progressScalers[NumProgressScalers]; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ThreadController); - }; -} \ No newline at end of file diff --git a/loris_library/Source/include/loris.h b/loris_library/Source/include/loris.h deleted file mode 100644 index 26d0d15..0000000 --- a/loris_library/Source/include/loris.h +++ /dev/null @@ -1,1020 +0,0 @@ -#ifndef INCLUDE_LORIS_H -#define INCLUDE_LORIS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * loris.h - * - * Header specifying C-linkable procedural interface for Loris. - * - * Main components of this interface: - * - version identification symbols - * - type declarations - * - Analyzer configuration - * - LinearEnvelope (formerly BreakpointEnvelope) operations - * - PartialList operations - * - Partial operations - * - Breakpoint operations - * - sound modeling functions for preparing PartialLists - * - utility functions for manipulating PartialLists - * - notification and exception handlers (all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function. The default one in Loris uses printf()). - * - * loris.h is generated automatically from loris.h.in. Do not modify loris.h - * - * Kelly Fitz, 4 Feb 2002 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -/* ---------------------------------------------------------------- */ -/* Version -/* -/* Define symbols that facilitate version/release identification. - */ - -#define LORIS_MAJOR_VERSION 1 -#define LORIS_MINOR_VERSION 8 -#define LORIS_SUBMINOR_VERSION -#define LORIS_VERSION_STR "Loris 1.8" - -/* ---------------------------------------------------------------- */ -/* Types -/* -/* The (class) types Breakpoint, LinearEnvelope, Partial, - and PartialList are imported from the Loris namespace. - The first three are classes, the latter is a typedef - for std::list< Loris::Partial >. - */ -#if defined(__cplusplus) - // include std library list header, declaring templates - // is too painful and fragile: - #include - - // declare Loris classes in Loris namespace: - namespace Loris - { - class Breakpoint; - class LinearEnvelope; - class Partial; - - // this typedef has to be copied from PartialList.h - typedef std::list< Loris::Partial > PartialList; - } - - // import those names into the global namespace - using Loris::Breakpoint; - using Loris::LinearEnvelope; - using Loris::Partial; - using Loris::PartialList; -#else - /* no classes, just declare types and use - opaque C pointers - */ - typedef struct Breakpoint Breakpoint; - typedef struct LinearEnvelope LinearEnvelope; - typedef struct PartialList PartialList; - typedef struct Partial Partial; -#endif - -/* - TODO - Maybe should also have loris_label_t and loris_size_t - defined, depending on configure. -*/ - -#if defined(__cplusplus) - extern "C" { -#endif - -/* ---------------------------------------------------------------- */ -/* Analyzer configuration -/* -/* An Analyzer represents a configuration of parameters for - performing Reassigned Bandwidth-Enhanced Additive Analysis - of sampled waveforms. This analysis process yields a collection - of Partials, each having a trio of synchronous, non-uniformly- - sampled breakpoint envelopes representing the time-varying - frequency, amplitude, and noisiness of a single bandwidth- - enhanced sinusoid. - - For more information about Reassigned Bandwidth-Enhanced - Analysis and the Reassigned Bandwidth-Enhanced Additive Sound - Model, refer to the Loris website: www.cerlsoundgroup.org/Loris/. - - In the procedural interface, there is only one Analyzer. - It must be configured by calling analyzer_configure before - any of the other analyzer operations can be performed. - */ - -void analyze( const double * buffer, unsigned int bufferSize, - double srate, PartialList * partials ); -/* Analyze an array of bufferSize (mono) samples at the given sample rate - (in Hz) and append the extracted Partials to the given - PartialList. - */ - -void analyzer_configure( double resolution, double windowWidth ); -/* Configure the sole Analyzer instance with the specified - frequency resolution (minimum instantaneous frequency - difference between Partials). All other Analyzer parameters - are computed from the specified frequency resolution. - - Construct the Analyzer instance if necessary. - - In the procedural interface, there is only one Analyzer. - It must be configured by calling analyzer_configure before - any of the other analyzer operations can be performed. - */ - -double analyzer_getAmpFloor( void ); -/* Return the amplitude floor (lowest detected spectral amplitude), - in (negative) dB, for the Loris Analyzer. - */ - -double analyzer_getCropTime( void ); -/* Return the crop time (maximum temporal displacement of a time- - frequency data point from the time-domain center of the analysis - window, beyond which data points are considered "unreliable") - for the Loris Analyzer. - */ - -double analyzer_getFreqDrift( void ); -/* Return the maximum allowable frequency difference between - consecutive Breakpoints in a Partial envelope for the Loris Analyzer. - */ - -double analyzer_getFreqFloor( void ); -/* Return the frequency floor (minimum instantaneous Partial - frequency), in Hz, for the Loris Analyzer. - */ - -double analyzer_getFreqResolution( void ); -/* Return the frequency resolution (minimum instantaneous frequency - difference between Partials) for the Loris Analyzer. - */ - -double analyzer_getHopTime( void ); -/* Return the hop time (which corresponds approximately to the - average density of Partial envelope Breakpoint data) for this - Analyzer. - */ - -double analyzer_getSidelobeLevel( void ); -/* Return the sidelobe attenutation level for the Kaiser analysis window in - positive dB. Higher numbers (e.g. 90) give very good sidelobe - rejection but cause the window to be longer in time. Smaller - numbers raise the level of the sidelobes, increasing the likelihood - of frequency-domain interference, but allow the window to be shorter - in time. - */ - -double analyzer_getWindowWidth( void ); -/* Return the frequency-domain main lobe width (measured between - zero-crossings) of the analysis window used by the Loris Analyzer. - */ - -void analyzer_setAmpFloor( double x ); -/* Set the amplitude floor (lowest detected spectral amplitude), in - (negative) dB, for the Loris Analyzer. - */ - -void analyzer_setBwRegionWidth( double x ); -/* Deprecated, use analyzer_storeResidueBandwidth instead. - */ - -void analyzer_setCropTime( double x ); -/* Set the crop time (maximum temporal displacement of a time- - frequency data point from the time-domain center of the analysis - window, beyond which data points are considered "unreliable") - for the Loris Analyzer. - */ - -void analyzer_setFreqDrift( double x ); -/* Set the maximum allowable frequency difference between - consecutive Breakpoints in a Partial envelope for the Loris Analyzer. - */ - -void analyzer_setFreqFloor( double x ); -/* Set the amplitude floor (minimum instantaneous Partial - frequency), in Hz, for the Loris Analyzer. - */ - -void analyzer_setFreqResolution( double x ); -/* Set the frequency resolution (minimum instantaneous frequency - difference between Partials) for the Loris Analyzer. (Does not cause - other parameters to be recomputed.) - */ - -void analyzer_setHopTime( double x ); -/* Set the hop time (which corresponds approximately to the average - density of Partial envelope Breakpoint data) for the Loris Analyzer. - */ - -void analyzer_setSidelobeLevel( double x ); -/* Set the sidelobe attenutation level for the Kaiser analysis window in - positive dB. Larger numbers (e.g. 90) give very good sidelobe - rejection but cause the window to be longer in time. Smaller - numbers raise the level of the sidelobes, increasing the likelihood - of frequency-domain interference, but allow the window to be shorter - in time. - */ - -void analyzer_setWindowWidth( double x ); -/* Set the frequency-domain main lobe width (measured between - zero-crossings) of the analysis window used by the Loris Analyzer. - */ - -void analyzer_storeResidueBandwidth( double regionWidth ); -/* Construct Partial bandwidth envelopes during analysis - by associating residual energy in the spectrum (after - peak extraction) with the selected spectral peaks that - are used to construct Partials. - - regionWidth is the width (in Hz) of the bandwidth - association regions used by this process, must be positive. - */ - -void analyzer_storeConvergenceBandwidth( double tolerancePct ); -/* Construct Partial bandwidth envelopes during analysis - by storing the mixed derivative of short-time phase, - scaled and shifted so that a value of 0 corresponds - to a pure sinusoid, and a value of 1 corresponds to a - bandwidth-enhanced sinusoid with maximal energy spread - (minimum sinusoidal convergence). - - tolerance is the amount of range over which the - mixed derivative indicator should be allowed to drift away - from a pure sinusoid before saturating. This range is mapped - to bandwidth values on the range [0,1]. Must be positive and - not greater than 1. - */ - -void analyzer_storeNoBandwidth( void ); -/* Disable bandwidth envelope construction. Bandwidth - will be zero for all Breakpoints in all Partials. - */ - -double analyzer_getBwRegionWidth( void ); -/* Return the width (in Hz) of the Bandwidth Association regions - used by this Analyzer, only if the spectral residue method is - used to compute bandwidth envelopes. Return zero if the mixed - derivative method is used, or if no bandwidth is computed. - */ - -double analyzer_getBwConvergenceTolerance( void ); -/* Return the mixed derivative convergence tolerance - only if the convergence indicator is used to compute - bandwidth envelopes. Return zero if the spectral residue - method is used or if no bandwidth is computed. - */ - - -/* ---------------------------------------------------------------- */ -/* LinearEnvelope object interface -/* -/* A LinearEnvelope represents a linear segment breakpoint - function with infinite extension at each end (that is, the - values past either end of the breakpoint function have the - values at the nearest end). - - In C++, a LinearEnvelope is a Loris::LinearEnvelope. - */ - -LinearEnvelope * createLinearEnvelope( void ); -/* Construct and return a new LinearEnvelope having no - breakpoints and an implicit value of 0. everywhere, - until the first breakpoint is inserted. - */ - -LinearEnvelope * copyLinearEnvelope( const LinearEnvelope * ptr_this ); -/* Construct and return a new LinearEnvelope that is an - exact copy of the specified LinearEnvelopes, having - an identical set of breakpoints. - */ - -void destroyLinearEnvelope( LinearEnvelope * ptr_this ); -/* Destroy this LinearEnvelope. - */ - -void linearEnvelope_insertBreakpoint( LinearEnvelope * ptr_this, - double time, double val ); -/* Insert a breakpoint representing the specified (time, value) - pair into this LinearEnvelope. If there is already a - breakpoint at the specified time, it will be replaced with - the new breakpoint. - */ - -double linearEnvelope_valueAt( const LinearEnvelope * ptr_this, - double time ); -/* Return the interpolated value of this LinearEnvelope at the - specified time. - */ - -/* ---------------------------------------------------------------- */ -/* PartialList object interface -/* -/* A PartialList represents a collection of Bandwidth-Enhanced - Partials, each having a trio of synchronous, non-uniformly- - sampled breakpoint envelopes representing the time-varying - frequency, amplitude, and noisiness of a single bandwidth- - enhanced sinusoid. - - For more information about Bandwidth-Enhanced Partials and the - Reassigned Bandwidth-Enhanced Additive Sound Model, refer to - the Loris website: www.cerlsoundgroup.org/Loris/. - - In C++, a PartialList is a Loris::PartialList. - */ -PartialList * createPartialList( void ); -/* Return a new empty PartialList. - */ - -void destroyPartialList( PartialList * ptr_this ); -/* Destroy this PartialList. - */ - -void partialList_clear( PartialList * ptr_this ); -/* Remove (and destroy) all the Partials from this PartialList, - leaving it empty. - */ - -void partialList_copy( PartialList * ptr_this, - const PartialList * src ); -/* Make this PartialList a copy of the source PartialList by making - copies of all of the Partials in the source and adding them to - this PartialList. - */ - -unsigned long partialList_size( const PartialList * ptr_this ); -/* Return the number of Partials in this PartialList. - */ - -void partialList_splice( PartialList * ptr_this, - PartialList * src ); -/* Splice all the Partials in the source PartialList onto the end of - this PartialList, leaving the source empty. - */ - -/* ---------------------------------------------------------------- */ -/* Partial object interface -/* -/* A Partial represents a single component in the - reassigned bandwidth-enhanced additive model. A Partial consists of a - chain of Breakpoints describing the time-varying frequency, amplitude, - and bandwidth (or noisiness) envelopes of the component, and a 4-byte - label. The Breakpoints are non-uniformly distributed in time. For more - information about Reassigned Bandwidth-Enhanced Analysis and the - Reassigned Bandwidth-Enhanced Additive Sound Model, refer to the Loris - website: www.cerlsoundgroup.org/Loris/. - */ - -double partial_startTime( const Partial * p ); -/* Return the start time (seconds) for the specified Partial. - */ - -double partial_endTime( const Partial * p ); -/* Return the end time (seconds) for the specified Partial. - */ - -double partial_duration( const Partial * p ); -/* Return the duration (seconds) for the specified Partial. - */ - -double partial_initialPhase( const Partial * p ); -/* Return the initial phase (radians) for the specified Partial. - */ - -int partial_label( const Partial * p ); -/* Return the integer label for the specified Partial. - */ - -unsigned long partial_numBreakpoints( const Partial * p ); -/* Return the number of Breakpoints in the specified Partial. - */ - -double partial_frequencyAt( const Partial * p, double t ); -/* Return the frequency (Hz) of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ - -double partial_bandwidthAt( const Partial * p, double t ); -/* Return the bandwidth of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ - -double partial_phaseAt( const Partial * p, double t ); -/* Return the phase (radians) of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ - -double partial_amplitudeAt( const Partial * p, double t ); -/* Return the (absolute) amplitude of the specified Partial interpolated - at a particular time. Partials are assumed to fade out - over 1 millisecond at the ends (rather than instantaneously). - It is an error to apply this function to a Partial having no Breakpoints. - */ - -void partial_setLabel( Partial * p, int label ); -/* Assign a new integer label to the specified Partial. - */ - -/* ---------------------------------------------------------------- */ -/* Breakpoint object interface -/* -/* A Breakpoint represents a single breakpoint in the - Partial parameter (frequency, amplitude, bandwidth) envelope. - Instantaneous phase is also stored, but is only used at the onset of - a partial, or when it makes a transition from zero to nonzero amplitude. - - Loris Partials represent reassigned bandwidth-enhanced model components. - A Partial consists of a chain of Breakpoints describing the time-varying - frequency, amplitude, and bandwidth (noisiness) of the component. - For more information about Reassigned Bandwidth-Enhanced - Analysis and the Reassigned Bandwidth-Enhanced Additive Sound - Model, refer to the Loris website: - www.cerlsoundgroup.org/Loris/. - */ - -double breakpoint_getAmplitude( const Breakpoint * bp ); -/* Return the (absolute) amplitude of the specified Breakpoint. - */ - -double breakpoint_getBandwidth( const Breakpoint * bp ); -/* Return the bandwidth coefficient of the specified Breakpoint. - */ - -double breakpoint_getFrequency( const Breakpoint * bp ); -/* Return the frequency (Hz) of the specified Breakpoint. - */ - -double breakpoint_getPhase( const Breakpoint * bp ); -/* Return the phase (radians) of the specified Breakpoint. - */ - -void breakpoint_setAmplitude( Breakpoint * bp, double a ); -/* Assign a new (absolute) amplitude to the specified Breakpoint. - */ - -void breakpoint_setBandwidth( Breakpoint * bp, double bw ); -/* Assign a new bandwidth coefficient to the specified Breakpoint. - */ - -void breakpoint_setFrequency( Breakpoint * bp, double f ); -/* Assign a new frequency (Hz) to the specified Breakpoint. - */ - -void breakpoint_setPhase( Breakpoint * bp, double phi ); -/* Assign a new phase (radians) to the specified Breakpoint. - */ - -/* ---------------------------------------------------------------- */ -/* non-object-based procedures -/* -/* Operations in Loris that need not be accessed though object - interfaces are represented as simple functions. - */ - -void channelize( PartialList * partials, - LinearEnvelope * refFreqEnvelope, int refLabel ); -/* Label Partials in a PartialList with the integer nearest to - the amplitude-weighted average ratio of their frequency envelope - to a reference frequency envelope. The frequency spectrum is - partitioned into non-overlapping channels whose time-varying - center frequencies track the reference frequency envelope. - The reference label indicates which channel's center frequency - is exactly equal to the reference envelope frequency, and other - channels' center frequencies are multiples of the reference - envelope frequency divided by the reference label. Each Partial - in the PartialList is labeled with the number of the channel - that best fits its frequency envelope. The quality of the fit - is evaluated at the breakpoints in the Partial envelope and - weighted by the amplitude at each breakpoint, so that high- - amplitude breakpoints contribute more to the channel decision. - Partials are labeled, but otherwise unmodified. In particular, - their frequencies are not modified in any way. - */ - -void collate( PartialList * partials ); -/* Collate unlabeled (zero-labeled) Partials into the smallest-possible - number of Partials that does not combine any overlapping Partials. - Collated Partials appear at the end of the sequence, after all - labeled Partials. - */ - -LinearEnvelope * -createFreqReference( PartialList * partials, - double minFreq, double maxFreq, long numSamps ); -/* Return a newly-constructed LinearEnvelope using the legacy - FrequencyReference class. The envelope will have approximately - the specified number of samples. The specified number of samples - must be greater than 1. Uses the FundamentalEstimator - (FundamentalFromPartials) class to construct an estimator of - fundamental frequency, configured to emulate the behavior of - the FrequencyReference class in Loris 1.4-1.5.2. If numSamps - is zero, construct the reference envelope from fundamental - estimates taken every five milliseconds. - - For simple sounds, this frequency reference may be a - good first approximation to a reference envelope for - channelization (see channelize()). - - Clients are responsible for disposing of the newly-constructed - LinearEnvelope. - */ - -LinearEnvelope * -createF0Estimate( PartialList * partials, double minFreq, double maxFreq, - double interval ); -/* Return a newly-constructed LinearEnvelope that estimates - the time-varying fundamental frequency of the sound - represented by the Partials in a PartialList. This uses - the FundamentalEstimator (FundamentalFromPartials) - class to construct an estimator of fundamental frequency, - and returns a LinearEnvelope that samples the estimator at the - specified time interval (in seconds). Default values are used - to configure the estimator. Only estimates in the specified - frequency range will be considered valid, estimates outside this - range will be ignored. - - Clients are responsible for disposing of the newly-constructed - LinearEnvelope. - */ - -void dilate( PartialList * partials, - const double * initial, const double * target, int npts ); -/* Dilate Partials in a PartialList according to the given - initial and target time points. Partial envelopes are - stretched and compressed so that temporal features at - the initial time points are aligned with the final time - points. Time points are sorted, so Partial envelopes are - are only stretched and compressed, but breakpoints are not - reordered. Duplicate time points are allowed. There must be - the same number of initial and target time points. - */ - -void distill( PartialList * partials ); -/* Distill labeled (channelized) Partials in a PartialList into a - PartialList containing at most one Partial per label. Unlabeled - (zero-labeled) Partials are left unmodified at the end of the - distilled Partials. - */ - -void exportAiff( const char * path, const double * buffer, - unsigned int bufferSize, double samplerate, int bitsPerSamp ); -/* Export mono audio samples stored in an array of size bufferSize to - an AIFF file having the specified sample rate at the given file path - (or name). The floating point samples in the buffer are clamped to the - range (-1.,1.) and converted to integers having bitsPerSamp bits. - */ - -void exportSdif( const char * path, PartialList * partials ); -/* Export Partials in a PartialList to a SDIF file at the specified - file path (or name). SDIF data is described by RBEM and RBEL - matrices. - For more information about SDIF, see the SDIF web site at: - www.ircam.fr/equipes/analyse-synthese/sdif/ - */ - -void exportSpc( const char * path, PartialList * partials, double midiPitch, - int enhanced, double endApproachTime ); -/* Export Partials in a PartialList to a Spc file at the specified file - path (or name). The fractional MIDI pitch must be specified. The - enhanced parameter defaults to true (for bandwidth-enhanced spc files), - but an be specified false for pure-sines spc files. The endApproachTime - parameter is in seconds. A nonzero endApproachTime indicates that the plist does - not include a release, but rather ends in a static spectrum corresponding - to the final breakpoint values of the partials. The endApproachTime - specifies how long before the end of the sound the amplitude, frequency, - and bandwidth values are to be modified to make a gradual transition to - the static spectrum. - */ - -/* Apply a reference Partial to fix the frequencies of Breakpoints - whose amplitude is below threshold_dB. 0 harmonifies full-amplitude - Partials, to apply only to quiet Partials, specify a lower - threshold like -90). The reference Partial is the first Partial - in the PartialList labeled refLabel (usually 1). The LinearEnvelope - is a time-varying weighting on the harmonifing process. When 1, - harmonic frequencies are used, when 0, breakpoint frequencies are - unmodified. - */ -void harmonify( PartialList * partials, long refLabel, - const LinearEnvelope * env, double threshold_dB ); - -unsigned int importAiff( const char * path, double * buffer, unsigned int bufferSize, - double * samplerate ); -/* Import audio samples stored in an AIFF file at the given file - path (or name). The samples are converted to floating point - values on the range (-1.,1.) and stored in an array of doubles. - The value returned is the number of samples in buffer, and it is at - most bufferSize. If samplerate is not a NULL pointer, - then, on return, it points to the value of the sample rate (in - Hz) of the AIFF samples. The AIFF file must contain only a single - channel of audio data. The prior contents of buffer, if any, are - overwritten. - */ - -void importSdif( const char * path, PartialList * partials ); -/* Import Partials from an SDIF file at the given file path (or - name), and append them to a PartialList. - */ - -void importSpc( const char * path, PartialList * partials ); -/* Import Partials from an Spc file at the given file path (or - name), and return them in a PartialList. - */ - -void morph( const PartialList * src0, const PartialList * src1, - const LinearEnvelope * ffreq, - const LinearEnvelope * famp, - const LinearEnvelope * fbw, - PartialList * dst ); -/* Morph labeled Partials in two PartialLists according to the - given frequency, amplitude, and bandwidth (noisiness) morphing - envelopes, and append the morphed Partials to the destination - PartialList. Loris morphs Partials by interpolating frequency, - amplitude, and bandwidth envelopes of corresponding Partials in - the source PartialLists. For more information about the Loris - morphing algorithm, see the Loris website: - www.cerlsoundgroup.org/Loris/ - */ - -void morphWithReference( const PartialList * src0, - const PartialList * src1, - long src0RefLabel, - long src1RefLabel, - const LinearEnvelope * ffreq, - const LinearEnvelope * famp, - const LinearEnvelope * fbw, - PartialList * dst ); -/* Morph labeled Partials in two PartialLists according to the - given frequency, amplitude, and bandwidth (noisiness) morphing - envelopes, and append the morphed Partials to the destination - PartialList. Specify the labels of the Partials to be used as - reference Partial for the two morph sources. The reference - partial is used to compute frequencies for very low-amplitude - Partials whose frequency estimates are not considered reliable. - The reference Partial is considered to have good frequency - estimates throughout. A reference label of 0 indicates that - no reference Partial should be used for the corresponding - morph source. - - Loris morphs Partials by interpolating frequency, - amplitude, and bandwidth envelopes of corresponding Partials in - the source PartialLists. For more information about the Loris - morphing algorithm, see the Loris website: - www.cerlsoundgroup.org/Loris/ - */ - -void morpher_setAmplitudeShape( double shape ); -/* Set the shaping parameter for the amplitude morphing - function. This shaping parameter controls the slope of - the amplitude morphing function, for values greater than - 1, this function gets nearly linear (like the old - amplitude morphing function), for values much less than - 1 (e.g. 1E-5) the slope is gently curved and sounds - pretty "linear", for very small values (e.g. 1E-12) the - curve is very steep and sounds un-natural because of the - huge jump from zero amplitude to very small amplitude. - - Use LORIS_DEFAULT_AMPMORPHSHAPE to obtain the default - amplitude morphing shape for Loris, (equal to 1E-5, - which works well for many musical instrument morphs, - unless Loris was compiled with the symbol - LINEAR_AMP_MORPHS defined, in which case - LORIS_DEFAULT_AMPMORPHSHAPE is equal to - LORIS_LINEAR_AMPMORPHSHAPE). - - Use LORIS_LINEAR_AMPMORPHSHAPE to approximate the linear - amplitude morphs performed by older versions of Loris. - - The amplitude shape must be positive. - */ - -extern const double LORIS_DEFAULT_AMPMORPHSHAPE; -extern const double LORIS_LINEAR_AMPMORPHSHAPE; - -void resample( PartialList * partials, double interval ); -/* Resample all Partials in a PartialList using the specified - sampling interval, so that the Breakpoints in the Partial - envelopes will all lie on a common temporal grid. - The Breakpoint times in resampled Partials will comprise a - contiguous sequence of integer multiples of the sampling interval, - beginning with the multiple nearest to the Partial's start time and - ending with the multiple nearest to the Partial's end time. Resampling - is performed in-place. - - */ - -void shapeSpectrum( PartialList * partials, PartialList * surface, - double stretchFreq, double stretchTime ); -/* Scale the amplitudes of a set of Partials by applying - a spectral suface constructed from another set. - Stretch the spectral surface in time and frequency - using the specified stretch factors. Set the stretch - factors to one for no stretching. - */ - -void sift( PartialList * partials ); -/* Identify overlapping Partials having the same (nonzero) - label. If any two partials with same label - overlap in time, set the label of the weaker - (having less total energy) partial to zero. - - */ - -unsigned int -synthesize( const PartialList * partials, - double * buffer, unsigned int bufferSize, - double srate ); -/* Synthesize Partials in a PartialList at the given sample - rate, and store the (floating point) samples in a buffer of - size bufferSize. The buffer is neither resized nor - cleared before synthesis, so newly synthesized samples are - added to any previously computed samples in the buffer, and - samples beyond the end of the buffer are lost. Return the - number of samples synthesized, that is, the index of the - latest sample in the buffer that was modified. - */ - -/* ---------------------------------------------------------------- */ -/* utility functions -/* -/* Operations for transforming and manipulating collections - of Partials. - */ - -double avgAmplitude( const Partial * p ); -/* Return the average amplitude over all Breakpoints in this Partial. - Return zero if the Partial has no Breakpoints. - */ - -double avgFrequency( const Partial * p ); -/* Return the average frequency over all Breakpoints in this Partial. - Return zero if the Partial has no Breakpoints. - */ - -void copyIf( const PartialList * src, PartialList * dst, - int ( * predicate )( const Partial * p, void * data ), - void * data ); -/* Append copies of Partials in the source PartialList satisfying the - specified predicate to the destination PartialList. The source list - is unmodified. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ - -void copyLabeled( const PartialList * src, long label, PartialList * dst ); -/* Append copies of Partials in the source PartialList having the - specified label to the destination PartialList. The source list - is unmodified. - */ - -void crop( PartialList * partials, double t1, double t2 ); -/* Trim Partials by removing Breakpoints outside a specified time span. - Insert a Breakpoint at the boundary when cropping occurs. Remove - any Partials that are left empty after cropping (Partials having no - Breakpoints between t1 and t2). - */ - -void extractIf( PartialList * src, PartialList * dst, - int ( * predicate )( const Partial * p, void * data ), - void * data ); -/* Remove Partials in the source PartialList satisfying the - specified predicate from the source list and append them to - the destination PartialList. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ - -void extractLabeled( PartialList * src, long label, PartialList * dst ); -/* Remove Partials in the source PartialList having the specified - label from the source list and append them to the destination - PartialList. - */ - -void fixPhaseAfter( PartialList * partials, double time ); -/* Recompute phases of all Breakpoints later than the specified - time so that the synthesized phases of those later Breakpoints - matches the stored phase, as long as the synthesized phase at - the specified time matches the stored (not recomputed) phase. - - Phase fixing is only applied to non-null (nonzero-amplitude) - Breakpoints, because null Breakpoints are interpreted as phase - reset points in Loris. If a null is encountered, its phase is - corrected from its non-Null successor, if it has one, otherwise - it is unmodified. - */ - -void fixPhaseAt( PartialList * partials, double time ); -/* Recompute phases of all Breakpoints in a Partial - so that the synthesized phases match the stored phases, - and the synthesized phase at (nearest) the specified - time matches the stored (not recomputed) phase. - - Backward phase-fixing stops if a null (zero-amplitude) - Breakpoint is encountered, because nulls are interpreted as - phase reset points in Loris. If a null is encountered, the - remainder of the Partial (the front part) is fixed in the - forward direction, beginning at the start of the Partial. - Forward phase fixing is only applied to non-null - (nonzero-amplitude) Breakpoints. If a null is encountered, - its phase is corrected from its non-Null successor, if - it has one, otherwise it is unmodified. - */ - -void fixPhaseBefore( PartialList * partials, double time ); -/* Recompute phases of all Breakpoints earlier than the specified - time so that the synthesized phases of those earlier Breakpoints - matches the stored phase, and the synthesized phase at the - specified time matches the stored (not recomputed) phase. - - Backward phase-fixing stops if a null (zero-amplitude) Breakpoint - is encountered, because nulls are interpreted as phase reset - points in Loris. If a null is encountered, the remainder of the - Partial (the front part) is fixed in the forward direction, - beginning at the start of the Partial. - */ - -void fixPhaseBetween( PartialList * partials, double tbeg, double tend ); -/* - Fix the phase travel between two times by adjusting the - frequency and phase of Breakpoints between those two times. - - This algorithm assumes that there is nothing interesting - about the phases of the intervening Breakpoints, and modifies - their frequencies as little as possible to achieve the correct - amount of phase travel such that the frequencies and phases at - the specified times match the stored values. The phases of all - the Breakpoints between the specified times are recomputed. - */ - -void fixPhaseForward( PartialList * partials, double tbeg, double tend ); -/* Recompute phases of all Breakpoints later than the specified - time so that the synthesized phases of those later Breakpoints - matches the stored phase, as long as the synthesized phase at - the specified time matches the stored (not recomputed) phase. - Breakpoints later than tend are unmodified. - - Phase fixing is only applied to non-null (nonzero-amplitude) - Breakpoints, because null Breakpoints are interpreted as phase - reset points in Loris. If a null is encountered, its phase is - corrected from its non-Null successor, if it has one, otherwise - it is unmodified. - */ - -int forEachBreakpoint( Partial * p, - int ( * func )( Breakpoint * p, double time, void * data ), - void * data ); -/* Apply a function to each Breakpoint in a Partial. The function - is called once for each Breakpoint in the source Partial. The - function may modify the Breakpoint (but should not otherwise attempt - to modify the Partial). The data parameter can be used to supply extra - user-defined data to the function. Pass 0 if no additional data is needed. - The function should return 0 if successful. If the function returns - a non-zero value, then forEachBreakpoint immediately returns that value - without applying the function to any other Breakpoints in the Partial. - forEachBreakpoint returns zero if all calls to func return zero. - */ - -int forEachPartial( PartialList * src, - int ( * func )( Partial * p, void * data ), - void * data ); -/* Apply a function to each Partial in a PartialList. The function - is called once for each Partial in the source PartialList. The - function may modify the Partial (but should not attempt to modify - the PartialList). The data parameter can be used to supply extra - user-defined data to the function. Pass 0 if no additional data - is needed. The function should return 0 if successful. If the - function returns a non-zero value, then forEachPartial immediately - returns that value without applying the function to any other - Partials in the PartialList. forEachPartial returns zero if all - calls to func return zero. - */ - -double peakAmplitude( const Partial * p ); -/* Return the maximum amplitude achieved by a Partial. - */ - -void removeIf( PartialList * src, - int ( * predicate )( const Partial * p, void * data ), - void * data ); -/* Remove from a PartialList all Partials satisfying the - specified predicate. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ - -void removeLabeled( PartialList * src, long label ); -/* Remove from a PartialList all Partials having the specified label. - */ - -void scaleAmplitude( PartialList * partials, LinearEnvelope * ampEnv ); -/* Scale the amplitude of the Partials in a PartialList according - to an envelope representing a time-varying amplitude scale value. - */ - -void scaleAmp( PartialList * partials, LinearEnvelope * ampEnv ); -/* Bad old name for scaleAmplitude. - */ - -void scaleBandwidth( PartialList * partials, LinearEnvelope * bwEnv ); -/* Scale the bandwidth of the Partials in a PartialList according - to an envelope representing a time-varying bandwidth scale value. - */ - -void scaleFrequency( PartialList * partials, LinearEnvelope * freqEnv ); -/* Scale the frequency of the Partials in a PartialList according - to an envelope representing a time-varying frequency scale value. - */ - -void scaleNoiseRatio( PartialList * partials, LinearEnvelope * noiseEnv ); -/* Scale the relative noise content of the Partials in a PartialList - according to an envelope representing a (time-varying) noise energy - scale value. - */ - -void setBandwidth( PartialList * partials, LinearEnvelope * bwEnv ); -/* Set the bandwidth of the Partials in a PartialList according - to an envelope representing a time-varying bandwidth value. - */ - -void shiftPitch( PartialList * partials, LinearEnvelope * pitchEnv ); -/* Shift the pitch of all Partials in a PartialList according to - the given pitch envelope. The pitch envelope is assumed to have - units of cents (1/100 of a halfstep). - */ - -void shiftTime( PartialList * partials, double offset ); -/* Shift the time of all the Breakpoints in a Partial by a - constant amount. - */ - -void sortByLabel( PartialList * partials ); -/* Sort the Partials in a PartialList in order of increasing label. - The sort is stable; Partials having the same label are not - reordered. - */ - -void timeSpan( PartialList * partials, double * tmin, double * tmax ); -/* Return the minimum start time and maximum end time - in seconds of all Partials in this PartialList. The v - times are returned in the (non-null) pointers tmin - and tmax. - */ - -double weightedAvgFrequency( const Partial * p ); -/* Return the average frequency over all Breakpoints in this Partial, - weighted by the Breakpoint amplitudes. Return zero if the Partial - has no Breakpoints. - */ - -/* ---------------------------------------------------------------- */ -/* Notification and exception handlers -/* -/* An exception handler and a notifier may be specified. Both - are functions taking a const char * argument and returning - void. - */ - -void setExceptionHandler( void(*f)(const char *) ); -/* Specify a function to call when reporting exceptions. The - function takes a const char * argument, and returns void. - */ - -void setNotifier( void(*f)(const char *) ); -/* Specify a notification function. The function takes a - const char * argument, and returns void. - */ - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -#endif /* ndef INCLUDE_LORIS_H */ diff --git a/loris_library/Source/include/loris/AiffData.h b/loris_library/Source/include/loris/AiffData.h deleted file mode 100644 index fb07ed2..0000000 --- a/loris_library/Source/include/loris/AiffData.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * AiffData.h - * - * Declarations of import and export functions. - * - * Kelly Fitz, 17 Sept 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Marker.h" - -#include -#include - -// in case configure wasn't run (no config.h), -// pick some (hopefully-) reasonable values for -// these things and hope for the best... -#if ! defined( SIZEOF_SHORT ) -#define SIZEOF_SHORT 2 -#endif - -#if ! defined( SIZEOF_INT ) -#define SIZEOF_INT 4 -#endif - -#if ! defined( SIZEOF_LONG ) -#define SIZEOF_LONG 4 // not for DEC Alpha! -#endif - - -#if SIZEOF_SHORT == 2 -typedef short Int_16; -typedef unsigned short Uint_16; -#elif SIZEOF_INT == 2 -typedef int Int_16; -typedef unsigned int Uint_16; -#else -#error "cannot find an appropriate type for 16-bit integers" -#endif - -#if SIZEOF_INT == 4 -typedef int Int_32; -typedef unsigned int Uint_32; -#elif SIZEOF_LONG == 4 -typedef long Int_32; -typedef unsigned long Uint_32; -#else -#error "cannot find an appropriate type for 32-bit integers" -#endif - - -// begin namespace -namespace Loris { - -// -- chunk types -- -enum -{ - ContainerId = 0x464f524d, // 'FORM' - AiffType = 0x41494646, // 'AIFF' - CommonId = 0x434f4d4d, // 'COMM' - ApplicationSpecificId = 0x4150504c, // 'APPL' - SosEnvelopesId = 0x534f5365, // 'SOSe' - SoundDataId = 0x53534e44, // 'SSND' - InstrumentId = 0x494e5354, // 'INST' - MarkerId = 0x4d41524b // 'MARK' -}; - -typedef Uint_32 ID; -typedef char Byte; - -struct CkHeader -{ - ID id; - Uint_32 size; - - // providing this default constructor - // gives clients a way to determine whether - // a chunk has been read and assigned: - CkHeader( void ) : id(0), size(0) {} -}; - -struct ContainerCk -{ - CkHeader header; - ID formType; -}; - -struct CommonCk -{ - CkHeader header; - Int_16 channels; // number of channels - Int_32 sampleFrames; // channel independent sample frames - Int_16 bitsPerSample; // number of bits per sample - double srate; // sampling rate (stored in IEEE 10 byte format) -}; - -struct SoundDataCk -{ - CkHeader header; - Uint_32 offset; - Uint_32 blockSize; - - // sample frames follow - std::vector< Byte > sampleBytes; -}; - -struct MarkerCk -{ - CkHeader header; - Uint_16 numMarkers; - - struct Marker - { - Uint_16 markerID; - Uint_32 position; // position in uncompressed samples - std::string markerName; - }; - - std::vector< MarkerCk::Marker > markers; -}; - -struct InstrumentCk -{ - CkHeader header; - Byte baseNote; /* all notes are MIDI note numbers */ - Byte detune; /* cents off, only -50 to +50 are significant */ - Byte lowNote; - Byte highNote; - Byte lowVelocity; /* 1 to 127 */ - Byte highVelocity; /* 1 to 127 */ - Int_16 gain; /* in dB, 0 is normal */ - - struct Loop - { - Int_16 playMode; /* 0 - no loop, 1 - forward looping, 2 - backward looping */ - Uint_16 beginLoop; /* this is a reference to a markerID, so you always - ÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊ have to work with MARK and INST together!! */ - Uint_16 endLoop; - }; - - Loop sustainLoop; - Loop releaseLoop; -}; - - -struct SosEnvelopesCk -{ - CkHeader header; - Int_32 signature; // For SOS, should be 'SOSe' - Int_32 enhanced; // 0 for sine-only, 1 for bandwidth-enhanced - Int_32 validPartials; // Number of partials with data in them; the file must - // be padded out to the next higher 2**n partials; - // this number is doubled for enhanced files - - // skip validPartials * sizeof(Int_32) bytes of junk here - Int_32 resolution; // frame duration in microseconds - Int_32 quasiHarmonic; // how many of the partials are quasiharmonic - // skip - // (4*LargestLabel + 8 - validPartials - 2) * sizeof(Int_32) - // bytes of junk here - -/* - // this stuff is unbelievably nasty! - -#define initPhaseLth ( 4*LargestLabel + 8 ) - Int_32 initPhase[initPhaseLth]; // obsolete initial phase array; is VARIABLE LENGTH array - // this is big enough for a max of 512 enhanced partials plus values below -// Int_32 resolution; // frame duration in microseconds - #define SOSresolution( es ) initPhase[ spcEI.enhanced \ - ? 2 * spcEI.numPartials : spcEI.numPartials] - // follows the initPhase[] array - - -// Int_32 quasiHarmonic; // how many of the partials are quasiharmonic - #define SOSquasiHarmonic( es ) initPhase[ spcEI.enhanced \ - ? 2 * spcEI.numPartials + 1 : spcEI.numPartials + 1] - // follows the initPhase[] array -*/ -}; - -// --------------------------------------------------------------------------- -// readChunkHeader -// --------------------------------------------------------------------------- -// Read the id and chunk size from the current file position. -// Let exceptions propogate. -// -std::istream & -readChunkHeader( std::istream & s, CkHeader & h ); - - -// --------------------------------------------------------------------------- -// readApplicationSpecifcData -// --------------------------------------------------------------------------- -// Read the data in the ApplicationSpecific chunk, assume the stream is -// correctly positioned, and that the chunk header has already been read. -// -// Look for data specific to SPC files. Any other kind of Application -// Specific data is ignored. -// -std::istream & -readApplicationSpecifcData( std::istream & s, SosEnvelopesCk & ck, unsigned long chunkSize ); - - -// --------------------------------------------------------------------------- -// readCommonData -// --------------------------------------------------------------------------- -// Read the data in the Common chunk, assume the stream is correctly -// positioned, and that the chunk header has already been read. -// -std::istream & -readCommonData( std::istream & s, CommonCk & ck, unsigned long chunkSize ); - -// --------------------------------------------------------------------------- -// readContainer -// --------------------------------------------------------------------------- -// -std::istream & -readContainer( std::istream & s, ContainerCk & ck, unsigned long chunkSize ); - -// --------------------------------------------------------------------------- -// readInstrumentData -// --------------------------------------------------------------------------- -// -std::istream & -readInstrumentData( std::istream & s, InstrumentCk & ck, unsigned long chunkSize ); - -// --------------------------------------------------------------------------- -// readMarkerData -// --------------------------------------------------------------------------- -// -std::istream & -readMarkerData( std::istream & s, MarkerCk & ck, unsigned long chunkSize ); - -// --------------------------------------------------------------------------- -// readSampleData -// --------------------------------------------------------------------------- -// Read the data in the Sound Data chunk, assume the stream is correctly -// positioned, and that the chunk header has already been read. -// -std::istream & -readSampleData( std::istream & s, SoundDataCk & ck, unsigned long chunkSize ); - -// --------------------------------------------------------------------------- -// configureCommonCk -// --------------------------------------------------------------------------- -void -configureCommonCk( CommonCk & ck, unsigned long nFrames, unsigned int nChans, - unsigned int bps, double srate ); - -// --------------------------------------------------------------------------- -// configureContainer -// --------------------------------------------------------------------------- -// dataSize is the combined size of all other chunks in file. Configure -// them first, then add their sizes (with headers!). -// -void -configureContainer( ContainerCk & ck, unsigned long dataSize ); - -// --------------------------------------------------------------------------- -// configureInstrumentCk -// --------------------------------------------------------------------------- -void -configureInstrumentCk( InstrumentCk & ck, double midiNoteNum ); - -// --------------------------------------------------------------------------- -// configureMarkerCk -// --------------------------------------------------------------------------- -void -configureMarkerCk( MarkerCk & ck, const std::vector< Marker > & markers, - double srate ); - -// --------------------------------------------------------------------------- -// configureSoundDataCk -// --------------------------------------------------------------------------- -// -void -configureSoundDataCk( SoundDataCk & ck, const std::vector< double > & samples, - unsigned int bps ); - -// --------------------------------------------------------------------------- -// writeCommon -// --------------------------------------------------------------------------- -// -std::ostream & -writeCommonData( std::ostream & s, const CommonCk & ck ); - -// --------------------------------------------------------------------------- -// writeContainer -// --------------------------------------------------------------------------- -// -std::ostream & -writeContainer( std::ostream & s, const ContainerCk & ck ); - -// --------------------------------------------------------------------------- -// writeInstrumentData -// --------------------------------------------------------------------------- -std::ostream & -writeInstrumentData( std::ostream & s, const InstrumentCk & ck ); - -// --------------------------------------------------------------------------- -// writeMarkerData -// --------------------------------------------------------------------------- -std::ostream & -writeMarkerData( std::ostream & s, const MarkerCk & ck ); - -// --------------------------------------------------------------------------- -// writeSampleData -// --------------------------------------------------------------------------- -// -std::ostream & -writeSampleData( std::ostream & s, const SoundDataCk & ck ); - -// --------------------------------------------------------------------------- -// convertBytesToSamples -// --------------------------------------------------------------------------- -// Convert sample bytes to double precision floating point samples -// (-1.0, 1.0). The samples vector is resized to fit exactly as many -// samples as are represented in the bytes vector, and any prior -// contents are overwritten. -// -void -convertBytesToSamples( const std::vector< Byte > & bytes, - std::vector< double > & samples, unsigned int bps ); - -// --------------------------------------------------------------------------- -// convertSamplesToBytes -// --------------------------------------------------------------------------- -// Convert floating point samples (-1.0, 1.0) to bytes. -// The bytes vector is resized to fit exactly as many -// samples as are stored in the samples vector, and any prior -// contents are overwritten. -// -void -convertSamplesToBytes( const std::vector< double > & samples, - std::vector< Byte > & bytes, unsigned int bps ); - -} // end of namespace diff --git a/loris_library/Source/include/loris/AiffFile.h b/loris_library/Source/include/loris/AiffFile.h deleted file mode 100644 index 55c2bc7..0000000 --- a/loris_library/Source/include/loris/AiffFile.h +++ /dev/null @@ -1,388 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * AiffFile.h - * - * Definition of AiffFile class for sample import and export in Loris. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "Marker.h" -#include "Synthesizer.h" - -#if defined(NO_TEMPLATE_MEMBERS) -#include "PartialList.h" -#endif - -#include -#include -#include - -// begin namespace -namespace Loris { - -class Partial; - -// --------------------------------------------------------------------------- -// class AiffFile -// -//! Class AiffFile represents sample data in a AIFF-format samples -//! file, and manages file I/O and sample conversion. Since the sound -//! analysis and synthesis algorithms in Loris and the reassigned -//! bandwidth-enhanced representation are monaural, AiffFile imports -//! only monaural (single channel) AIFF-format samples files, though -//! it can create and export a new two-channel file from a pair of -//! sample vectors. -// -class AiffFile -{ -// -- public interface -- -public: - -// -- types -- - - //! The type of the sample storage in an AiffFile. - typedef std::vector< double > samples_type; - - //! The type of all size parameters for AiffFile. - typedef samples_type::size_type size_type; - - //! The type of AIFF marker storage in an AiffFile. - typedef std::vector< Marker > markers_type; - -// -- construction -- - - //! Initialize an instance of AiffFile by importing sample data from - //! the file having the specified filename or path. - //! - //! \param filename is the name or path of an AIFF samples file - explicit AiffFile( const std::string & filename ); - - //! Initialize an instance of AiffFile with samples rendered - //! from a sequnence of Partials. The Partials in the - //! specified half-open (STL-style) range are rendered at - //! the specified sample rate, using the (optionally) - //! specified Partial fade time (see Synthesizer.h - //! for an examplanation of fade time). Other synthesis - //! parameters are taken from the Synthesizer DefaultParameters. - //! - //! \sa Synthesizer::DefaultParameters - //! - //! \param begin_partials is the beginning of a sequence of Partials - //! \param end_partials is (one-past) the end of a sequence of - //! Partials - //! \param samplerate is the rate (Hz) at which Partials are rendered - //! \param fadeTime is the Partial fade time (seconds) for rendering - //! the Partials on the specified range. If unspecified, the - //! fade time is taken from the Synthesizer DefaultParameters. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. -#if !defined(NO_TEMPLATE_MEMBERS) - template - AiffFile( Iter begin_partials, Iter end_partials, - double samplerate, double fadeTime = FadeTimeUnspecified ); -#else - AiffFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double samplerate, double fadeTime = FadeTimeUnspecified ); -#endif - - //! Initialize an instance of AiffFile having the specified sample - //! rate, preallocating numFrames samples, initialized to zero. - //! - //! \param samplerate is the rate at which Partials are rendered - //! \param numFrames is the initial number of (zero) samples. If - //! unspecified, no samples are preallocated. - //! \param numChannels is the number of channels of audio data - //! to preallocate (default 1 channel) - AiffFile( double samplerate, size_type numFrames = 0, - unsigned int numChannels = 1 ); - - //! Initialize an instance of AiffFile from a buffer of sample - //! data, with the specified sample rate. - //! - //! \param buffer is a pointer to a buffer of floating point samples. - //! \param bufferlength is the number of samples in the buffer. - //! \param samplerate is the sample rate of the samples in the buffer. - AiffFile( const double * buffer, size_type bufferlength, double samplerate ); - - //! Initialize an instance of AiffFile from two buffers of sample - //! data, with the specified sample rate. Both buffers must store - //! the same number (bufferLength) of samples. - //! - //! \param buffer_left is a pointer to a buffer of floating point samples - //! representing the left channel samples. - //! \param buffer_right is a pointer to a buffer of floating point samples - //! representing the right channel samples. - //! \param bufferlength is the number of samples in the buffer. - //! \param samplerate is the sample rate of the samples in the buffer. - // - AiffFile( const double * buffer_left, const double * buffer_right, - size_type bufferlength, double samplerate ); - - //! Initialize an instance of AiffFile from a vector of sample - //! data, with the specified sample rate. - //! - //! \param vec is a vector of floating point samples. - //! \param samplerate is the sample rate of the samples in the vector. - AiffFile( const std::vector< double > & vec, double samplerate ); - - //! Initialize an instance of AiffFile from two vectors of sample - //! data, with the specified sample rate. If the two vectors have different - //! lengths, the shorter one is padded with zeros. - //! - //! \param vec_left is a vector of floating point samples representing the - //! left channel samples. - //! \param vec_right is a vector of floating point samples representing the - //! right channel samples. - //! \param samplerate is the sample rate of the samples in the vectors. - // - AiffFile( const std::vector< double > & vec_left, - const std::vector< double > & vec_right, - double samplerate ); - - //! Initialize this and AiffFile that is an exact copy, having - //! all the same sample data, as another AiffFile. - //! - //! \param other is the AiffFile to copy - AiffFile( const AiffFile & other ); - - //! Assignment operator: change this AiffFile to be an exact copy - //! of the specified AiffFile, rhs, that is, having the same sample - //! data. - //! - //! \param rhs is the AiffFile to replicate - AiffFile & operator= ( const AiffFile & rhs ); - -// -- access -- - - //! Return a reference to the Marker (see Marker.h) container - //! for this AiffFile. - markers_type & markers( void ); - - //! Return a const reference to the Marker (see Marker.h) container - //! for this AiffFile. - const markers_type & markers( void ) const; - - //! Return the fractional MIDI note number assigned to this AiffFile. - //! If the sound has no definable pitch, note number 60.0 is used. - double midiNoteNumber( void ) const; - - //! Return the number of channels of audio samples represented by - //! this AiffFile, 1 for mono, 2 for stereo. - unsigned int numChannels( void ) const; - - //! Return the number of sample frames represented in this AiffFile. - //! A sample frame contains one sample per channel for a single sample - //! interval (e.g. mono and stereo samples files having a sample rate of - //! 44100 Hz both have 44100 sample frames per second of audio samples). - size_type numFrames( void ) const; - - //! Bad old legacy name for numFrames. - //! \deprecated Use numFrames instead. - size_type sampleFrames( void ) const { return numFrames(); } - - //! Return the sampling freqency in Hz for the sample data in this - //! AiffFile. - double sampleRate( void ) const; - - //! Return a reference (or const reference) to the vector containing - //! the floating-point sample data for this AiffFile. - samples_type & samples( void ); - - //! Return a const reference (or const reference) to the vector containing - //! the floating-point sample data for this AiffFile. - const samples_type & samples( void ) const; - -// -- mutation -- - - //! Render the specified Partial using the (optionally) specified - //! Partial fade time (see Synthesizer.h for an examplanation - //! of fade time), and accumulate the resulting samples into - //! the sample vector for this AiffFile. Other synthesis parameters - //! are taken from the Synthesizer DefaultParameters. - //! - //! \sa Synthesizer::DefaultParameters - //! - //! \param p is the partial to render into this AiffFile - //! \param fadeTime is the Partial fade time for rendering - //! the Partials on the specified range. If unspecified, the - //! fade time is taken from the Synthesizer DefaultParameters. - void addPartial( const Loris::Partial & p, double fadeTime = FadeTimeUnspecified ); - - //! Accumulate samples rendered from a sequence of Partials. - //! The Partials in the specified half-open (STL-style) range are - //! rendered at this AiffFile's sample rate, using the (optionally) - //! specified Partial fade time (see Synthesizer.h for an examplanation - //! of fade time). Other synthesis parameters are taken from the - //! Synthesizer DefaultParameters. - //! - //! \sa Synthesizer::DefaultParameters - //! - //! \param begin_partials is the beginning of a sequence of Partials - //! \param end_partials is (one-past) the end of a sequence of - //! Partials - //! \param fadeTime is the Partial fade time for rendering - //! the Partials on the specified range. If unspecified, the - //! fade time is taken from the Synthesizer DefaultParameters. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. -#if !defined(NO_TEMPLATE_MEMBERS) - template - void addPartials( Iter begin_partials, Iter end_partials, - double fadeTime = FadeTimeUnspecified ); -#else - void addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double fadeTime = FadeTimeUnspecified ); -#endif - - //! Set the fractional MIDI note number assigned to this AiffFile. - //! If the sound has no definable pitch, use note number 60.0 (the default). - //! - //! \param nn is a fractional MIDI note number, 60 is middle C. - void setMidiNoteNumber( double nn ); - -// -- export -- - - //! Export the sample data represented by this AiffFile to - //! the file having the specified filename or path. Export - //! signed integer samples of the specified size, in bits - //! (8, 16, 24, or 32). - //! - //! \param filename is the name or path of the AIFF samples file - //! to be created or overwritten. - //! \param bps is the number of bits per sample to store in the - //! samples file (8, 16, 24, or 32).If unspeicified, 16 bits - void write( const std::string & filename, unsigned int bps = 16 ); - -private: -// -- implementation -- - double notenum_, rate_; // MIDI note number and sample rate - unsigned int numchans_; - markers_type markers_; // AIFF Markers - samples_type samples_; // floating point samples [-1.0, 1.0] - - -// -- helpers -- - - // Construct a Synthesizer for rendering Partials and set its fadeTime. - // Modify the default synthesizer parameters with this file's sample rate - // and, if specified (not equal to FadeTimeUnspecified), the fade time. - Synthesizer configureSynthesizer( double fadeTime ); - - // Import data from an AIFF file on disk. - void readAiffData( const std::string & filename ); - - enum { FadeTimeUnspecified = -9999999 }; - // This is not pretty, but it is better (perhaps) than defining two - // of every member having an optional fade time parameter. - -}; // end of class AiffFile - -// -- template members -- - -// --------------------------------------------------------------------------- -// constructor from Partial range -// --------------------------------------------------------------------------- -//! Initialize an instance of AiffFile with samples rendered -//! from a sequnence of Partials. The Partials in the -//! specified half-open (STL-style) range are rendered at -//! the specified sample rate, using the (optionally) -//! specified Partial fade time (see Synthesizer.h -//! for an examplanation of fade time). Other synthesis -//! parameters are taken from the Synthesizer DefaultParameters. -//! -//! \sa Synthesizer::DefaultParameters -//! -//! \param begin_partials is the beginning of a sequence of Partials -//! \param end_partials is (one-past) the end of a sequence of -//! Partials -//! \param samplerate is the rate (Hz) at which Partials are rendered -//! \param fadeTime is the Partial fade time (seconds) for rendering -//! the Partials on the specified range. If unspecified, the -//! fade time is taken from the Synthesizer DefaultParameters. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. -// -#if !defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > - AiffFile::AiffFile( Iter begin_partials, Iter end_partials, - double samplerate, double fadeTime ) : -#else - AiffFile::AiffFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double samplerate, double fadeTime ) : -#endif -// initializers: - notenum_( 60 ), - rate_( samplerate ), - numchans_( 1 ) -{ - addPartials( begin_partials, end_partials, fadeTime ); -} - -// --------------------------------------------------------------------------- -// addPartials -// --------------------------------------------------------------------------- -//! Accumulate samples rendered from a sequence of Partials. -//! The Partials in the specified half-open (STL-style) range are -//! rendered at this AiffFile's sample rate, using the (optionally) -//! specified Partial fade time (see Synthesizer.h for an examplanation -//! of fade time). Other synthesis parameters are taken from the -//! Synthesizer DefaultParameters. -//! -//! \sa Synthesizer::DefaultParameters -//! -//! \param begin_partials is the beginning of a sequence of Partials -//! \param end_partials is (one-past) the end of a sequence of -//! Partials -//! \param fadeTime is the Partial fade time for rendering -//! the Partials on the specified range. If unspecified, the -//! fade time is taken from the Synthesizer DefaultParameters. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. -// -#if !defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void - AiffFile::addPartials( Iter begin_partials, Iter end_partials, double fadeTime ) -#else -void - AiffFile::addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double fadeTime ) -#endif -{ - Synthesizer synth = configureSynthesizer( fadeTime ); - synth.synthesize( begin_partials, end_partials ); -} - -} // end of namespace Loris diff --git a/loris_library/Source/include/loris/Analyzer.h b/loris_library/Source/include/loris/Analyzer.h deleted file mode 100644 index 6bdfe52..0000000 --- a/loris_library/Source/include/loris/Analyzer.h +++ /dev/null @@ -1,620 +0,0 @@ -#ifndef INCLUDE_ANALYZER_H -#define INCLUDE_ANALYZER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Analyzer.h - * - * Definition of class Loris::Analyzer. - * - * Kelly Fitz, 5 Dec 99 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include -#include -#include "LinearEnvelope.h" -#include "Partial.h" -#include "PartialList.h" -// #include "SpectralPeaks.h" - -// begin namespace -namespace Loris { - -class Envelope; -class LinearEnvelopeBuilder; -// class Peaks; -// class Peaks::iterator; -// oooo, this is nasty, need to fix it! -class SpectralPeak; -typedef std::vector< SpectralPeak > Peaks; - -// --------------------------------------------------------------------------- -// class Analyzer -// -//! Class Analyzer represents a configuration of parameters for -//! performing Reassigned Bandwidth-Enhanced Additive Analysis -//! of sampled sounds. The analysis process yields a collection -//! of Partials, each having a trio of synchronous, non-uniformly- -//! sampled breakpoint envelopes representing the time-varying -//! frequency, amplitude, and noisiness of a single bandwidth- -//! enhanced sinusoid. These Partials are accumulated in the -//! Analyzer. -//! -//! The core analysis parameter is the frequency resolution, the -//! minimum instantaneous frequency spacing between partials. Most -//! other parameters are initially configured according to this -//! parameter (and the analysis window width, if specified). -//! Subsequent parameter mutations are independent. -//! -//! Bandwidth enhancement: -//! Two different strategies are available for computing bandwidth -//! (or noisiness) envelope: -//! -//! One strategy is to construct bandwidth envelopes during analysis -//! by associating residual energy in the spectrum (after peak -//! extraction) with the selected spectral peaks that are used -//! to construct Partials. This is the original bandwidth enhancement -//! algorithm, and bandwidth envelopes constructed in this way may -//! be suitable for use in bandwidth-enhanced synthesis. -//! -//! Another stategy is to construct bandwidth envelopes during -//! analysis by storing the mixed derivative of short-time phase, -//! scaled and shifted so that a value of 0 corresponds -//! to a pure sinusoid, and a value of 1 corresponds to a -//! bandwidth-enhanced sinusoid with maximal energy spread -//! (minimum convergence in frequency). These bandwidth envelopes -//! are not suitable for bandwidth-enhanced synthesis, be sure -//! to set the bandwidth to 0, or to disable bandwidth enhancement -//! before rendering. -//! -//! The Analyzer may be configured to use either of these two -//! strategies for bandwidth-enhanced analysis, or to construct -//! no bandwidth envelopes at all. If unspecified, the default -//! Analyzer configuration uses spectral residue to construct -//! bandwidth envelopes. -//! -//! \sa storeResidueBandwidth, storeConvergenceBandwidth, storeNoBandwidth -//! -//! For more information about Reassigned Bandwidth-Enhanced -//! Analysis and the Reassigned Bandwidth-Enhanced Additive Sound -//! Model, refer to the Loris website: www.cerlsoundgroup.org/Loris/. -// -class Analyzer -{ -// -- public interface -- -public: - -// -- construction -- - - //! Construct a new Analyzer configured with the given - //! frequency resolution (minimum instantaneous frequency - //! difference between Partials). All other Analyzer parameters - //! are computed from the specified frequency resolution. - //! - //! \param resolutionHz is the frequency resolution in Hz. - explicit Analyzer( double resolutionHz ); - - //! Construct a new Analyzer configured with the given - //! frequency resolution (minimum instantaneous frequency - //! difference between Partials) and analysis window width - //! (main lobe, zero-to-zero). All other Analyzer parameters - //! are computed from the specified resolution and window width. - //! - //! \param resolutionHz is the frequency resolution in Hz. - //! \param windowWidthHz is the main lobe width of the Kaiser - //! analysis window in Hz. - Analyzer( double resolutionHz, double windowWidthHz ); - - //! Construct a new Analyzer configured with the given time-varying - //! frequency resolution (minimum instantaneous frequency - //! difference between Partials) and analysis window width - //! (main lobe, zero-to-zero). All other Analyzer parameters - //! are computed from the specified resolution and window width. - //! - //! \param resolutionHz is the frequency resolution in Hz. - //! \param windowWidthHz is the main lobe width of the Kaiser - //! analysis window in Hz. - Analyzer( const Envelope & resolutionEnv, double windowWidthHz ); - - //! Construct a new Analyzer having identical - //! parameter configuration to another Analyzer. - //! The list of collected Partials is not copied. - //! - //! \param other is the Analyzer to copy. - Analyzer( const Analyzer & other ); - - //! Destroy this Analyzer. - ~Analyzer( void ); - - //! Construct a new Analyzer having identical - //! parameter configuration to another Analyzer. - //! The list of collected Partials is not copied. - //! - //! \param rhs is the Analyzer to copy. - Analyzer & operator=( const Analyzer & rhs ); - -// -- configuration -- - - //! Configure this Analyzer with the given frequency resolution - //! (minimum instantaneous frequency difference between Partials, - //! in Hz). All other Analyzer parameters are (re-)computed from the - //! frequency resolution, including the window width, which is - //! twice the resolution. - //! - //! \param resolutionHz is the frequency resolution in Hz. - void configure( double resolutionHz ); - - //! Configure this Analyzer with the given frequency resolution - //! (minimum instantaneous frequency difference between Partials) - //! and analysis window width (main lobe, zero-to-zero, in Hz). - //! All other Analyzer parameters are (re-)computed from the - //! frequency resolution and window width. - //! - //! \param resolutionHz is the frequency resolution in Hz. - //! \param windowWidthHz is the main lobe width of the Kaiser - //! analysis window in Hz. - //! - //! There are three categories of analysis parameters: - //! - the resolution, and params that are usually related to (or - //! identical to) the resolution (frequency floor and drift) - //! - the window width and params that are usually related to (or - //! identical to) the window width (hop and crop times) - //! - independent parameters (bw region width and amp floor) - void configure( double resolutionHz, double windowWidthHz ); - - //! Configure this Analyzer with the given time-varying frequency resolution - //! (minimum instantaneous frequency difference between Partials) - //! and analysis window width (main lobe, zero-to-zero, in Hz). - //! All other Analyzer parameters are (re-)computed from the - //! frequency resolution and window width. - //! - //! \param resolutionEnv is the time-varying frequency resolution - //! in Hz. - //! \param windowWidthHz is the main lobe width of the Kaiser - //! analysis window in Hz. - //! - //! There are three categories of analysis parameters: - //! - the resolution, and params that are usually related to (or - //! identical to) the resolution (frequency floor and drift) - //! - the window width and params that are usually related to (or - //! identical to) the window width (hop and crop times) - //! - independent parameters (bw region width and amp floor) - // - void configure( const Envelope & resolutionEnv, double windowWidthHz ); - -// -- analysis -- - - //! Analyze a vector of (mono) samples at the given sample rate - //! (in Hz) and store the extracted Partials in the Analyzer's - //! PartialList (std::list of Partials). - //! - //! \param vec is a vector of floating point samples - //! \param srate is the sample rate of the samples in the vector - void analyze( const std::vector & vec, double srate ); - - //! Analyze a range of (mono) samples at the given sample rate - //! (in Hz) and store the extracted Partials in the Analyzer's - //! PartialList (std::list of Partials). - //! - //! \param bufBegin is a pointer to a buffer of floating point samples - //! \param bufEnd is (one-past) the end of a buffer of floating point - //! samples - //! \param srate is the sample rate of the samples in the buffer - void analyze( const double * bufBegin, const double * bufEnd, double srate ); - -// -- tracking analysis -- - - //! Analyze a vector of (mono) samples at the given sample rate - //! (in Hz) and store the extracted Partials in the Analyzer's - //! PartialList (std::list of Partials). Use the specified envelope - //! as a frequency reference for Partial tracking. - //! - //! \param vec is a vector of floating point samples - //! \param srate is the sample rate of the samples in the vector - //! \param reference is an Envelope having the approximate - //! frequency contour expected of the resulting Partials. - void analyze( const std::vector & vec, double srate, - const Envelope & reference ); - - //! Analyze a range of (mono) samples at the given sample rate - //! (in Hz) and store the extracted Partials in the Analyzer's - //! PartialList (std::list of Partials). Use the specified envelope - //! as a frequency reference for Partial tracking. - //! - //! \param bufBegin is a pointer to a buffer of floating point samples - //! \param bufEnd is (one-past) the end of a buffer of floating point - //! samples - //! \param srate is the sample rate of the samples in the buffer - //! \param reference is an Envelope having the approximate - //! frequency contour expected of the resulting Partials. - void analyze( const double * bufBegin, const double * bufEnd, double srate, - const Envelope & reference ); - -// -- parameter access -- - - //! Return the amplitude floor (lowest detected spectral amplitude), - //! in (negative) dB, for this Analyzer. - double ampFloor( void ) const; - - //! Return the crop time (maximum temporal displacement of a time- - //! frequency data point from the time-domain center of the analysis - //! window, beyond which data points are considered "unreliable") - //! for this Analyzer. - double cropTime( void ) const; - - //! Return the maximum allowable frequency difference between - //! consecutive Breakpoints in a Partial envelope for this Analyzer. - double freqDrift( void ) const; - - //! Return the frequency floor (minimum instantaneous Partial - //! frequency), in Hz, for this Analyzer. - double freqFloor( void ) const; - - //! Return the frequency resolution (minimum instantaneous frequency - //! difference between Partials) for this Analyzer at the specified - //! time in seconds. If no time is specified, then the initial resolution - //! (at 0 seconds) is returned. - //! - //! \param time is the time in seconds at which to evaluate the - //! frequency resolution - double freqResolution( double time = 0.0 ) const; - - //! Return the hop time (which corresponds approximately to the - //! average density of Partial envelope Breakpoint data) for this - //! Analyzer. - double hopTime( void ) const; - - //! Return the sidelobe attenutation level for the Kaiser analysis window in - //! positive dB. Larger numbers (e.g. 90) give very good sidelobe - //! rejection but cause the window to be longer in time. Smaller numbers - //! (like 60) raise the level of the sidelobes, increasing the likelihood - //! of frequency-domain interference, but allow the window to be shorter - //! in time. - double sidelobeLevel( void ) const; - - //! Return the frequency-domain main lobe width (measured between - //! zero-crossings) of the analysis window used by this Analyzer. - double windowWidth( void ) const; - - //! Return true if the phases and frequencies of the constructed - //! partials should be modified to be consistent at the end of the - //! analysis, and false otherwise. (Default is true.) - bool phaseCorrect( void ) const; - - -// -- parameter mutation -- - - //! Set the amplitude floor (lowest detected spectral amplitude), in - //! (negative) dB, for this Analyzer. - //! - //! \param x is the new value of this parameter. - void setAmpFloor( double x ); - - //! Set the crop time (maximum temporal displacement of a time- - //! frequency data point from the time-domain center of the analysis - //! window, beyond which data points are considered "unreliable") - //! for this Analyzer. - //! - //! \param x is the new value of this parameter. - void setCropTime( double x ); - - //! Set the maximum allowable frequency difference between - //! consecutive Breakpoints in a Partial envelope for this Analyzer. - //! - //! \param x is the new value of this parameter. - void setFreqDrift( double x ); - - //! Set the frequency floor (minimum instantaneous Partial - //! frequency), in Hz, for this Analyzer. - //! - //! \param x is the new value of this parameter. - void setFreqFloor( double x ); - - //! Set the frequency resolution (minimum instantaneous frequency - //! difference between Partials) for this Analyzer. (Does not cause - //! other parameters to be recomputed.) - //! - //! \param x is the new value of this parameter. - void setFreqResolution( double x ); - - //! Set the time-varying frequency resolution (minimum instantaneous frequency - //! difference between Partials) for this Analyzer. (Does not cause - //! other parameters to be recomputed.) - //! - //! \param e is the envelope to copy for this parameter. - void setFreqResolution( const Envelope & e ); - - //! Set the hop time (which corresponds approximately to the average - //! density of Partial envelope Breakpoint data) for this Analyzer. - //! - //! \param x is the new value of this parameter. - void setHopTime( double x ); - - //! Set the sidelobe attenutation level for the Kaiser analysis window in - //! positive dB. More negative numbers (e.g. -90) give very good sidelobe - //! rejection but cause the window to be longer in time. Less negative - //! numbers raise the level of the sidelobes, increasing the likelihood - //! of frequency-domain interference, but allow the window to be shorter - //! in time. - //! - //! \param x is the new value of this parameter. - void setSidelobeLevel( double x ); - - //! Set the frequency-domain main lobe width (measured between - //! zero-crossings) of the analysis window used by this Analyzer. - //! - //! \param x is the new value of this parameter. - void setWindowWidth( double x ); - - //! Indicate whether the phases and frequencies of the constructed - //! partials should be modified to be consistent at the end of the - //! analysis. (Default is true.) - //! - //! \param TF is a flag indicating whether or not to construct - //! phase-corrected Partials - void setPhaseCorrect( bool TF = true ); - - -// -- bandwidth envelope specification -- - - enum { Default_ResidueBandwidth_RegionWidth = 2000, - Default_ConvergenceBandwidth_TolerancePct = 10 }; - - //! Construct Partial bandwidth envelopes during analysis - //! by associating residual energy in the spectrum (after - //! peak extraction) with the selected spectral peaks that - //! are used to construct Partials. - //! - //! This is the default bandwidth-enhancement strategy. - //! - //! \param regionWidth is the width (in Hz) of the bandwidth - //! association regions used by this process, must be positive. - //! If unspecified, a default value is used. - void storeResidueBandwidth( double regionWidth = Default_ResidueBandwidth_RegionWidth ); - - //! Construct Partial bandwidth envelopes during analysis - //! by storing the mixed derivative of short-time phase, - //! scaled and shifted so that a value of 0 corresponds - //! to a pure sinusoid, and a value of 1 corresponds to a - //! bandwidth-enhanced sinusoid with maximal energy spread - //! (minimum sinusoidal convergence). - //! - //! \param tolerance is the amount of range over which the - //! mixed derivative indicator should be allowed to drift away - //! from a pure sinusoid before saturating. This range is mapped - //! to bandwidth values on the range [0,1]. Must be positive and - //! not greater than 1. If unspecified, a default value is used. - void storeConvergenceBandwidth( double tolerancePct = - 0.01 * (double)Default_ConvergenceBandwidth_TolerancePct ); - - //! Disable bandwidth envelope construction. Bandwidth - //! will be zero for all Breakpoints in all Partials. - void storeNoBandwidth( void ); - - //! Return true if this Analyzer is configured to compute - //! bandwidth envelopes using the spectral residue after - //! peaks have been identified, and false otherwise. - bool bandwidthIsResidue( void ) const; - - //! Return true if this Analyzer is configured to compute - //! bandwidth envelopes using the mixed derivative convergence - //! indicator, and false otherwise. - bool bandwidthIsConvergence( void ) const; - - //! Return the width (in Hz) of the Bandwidth Association regions - //! used by this Analyzer, only if the spectral residue method is - //! used to compute bandwidth envelopes. Return zero if the mixed - //! derivative method is used, or if no bandwidth is computed. - double bwRegionWidth( void ) const; - - //! Return the mixed derivative convergence tolerance (percent) - //! only if the convergence indicator is used to compute - //! bandwidth envelopes. Return zero if the spectral residue - //! method is used or if no bandwidth is computed. - double bwConvergenceTolerance( void ) const; - - //! Return true if bandwidth envelopes are to be constructed - //! by any means, that is, if either bandwidthIsResidue() or - //! bandwidthIsConvergence() are true. Otherwise, return - //! false. - bool associateBandwidth( void ) const - { return bandwidthIsResidue() || bandwidthIsConvergence(); } - - //! Deprecated, use storeResidueBandwidth or storeNoBandwidth instead. - void setBwRegionWidth( double x ) - { - if ( x != 0 ) - { - storeResidueBandwidth( x ); - } - else - { - storeNoBandwidth(); - } - } - - -// -- PartialList access -- - - //! Return a mutable reference to this Analyzer's list of - //! analyzed Partials. - PartialList & partials( void ); - - //! Return an immutable (const) reference to this Analyzer's - //! list of analyzed Partials. - const PartialList & partials( void ) const; - -// -- envelope access -- - - enum { Default_FundamentalEnv_ThreshDb = -60, - Default_FundamentalEnv_ThreshHz = 8000 }; - - //! Specify parameters for constructing a fundamental frequency - //! envelope for the analyzed sound during analysis. The fundamental - //! frequency estimate can be accessed by fundamentalEnv() after the - //! analysis is complete. - //! - //! By default, a fundamental envelope is estimated during analysis - //! between the frequency resolution and 1.5 times the resolution. - //! - //! \param fmin is the lower bound on the fundamental frequency estimate - //! \param fmax is the upper bound on the fundamental frequency estimate - //! \param threshDb is the lower bound on the amplitude of a spectral peak - //! that will constribute to the fundamental frequency estimate (very - //! low amplitude peaks tend to have less reliable frequency estimates). - //! Default is -60 dB. - //! \param threshHz is the upper bound on the frequency of a spectral - //! peak that will constribute to the fundamental frequency estimate. - //! Default is 8 kHz. - void buildFundamentalEnv( double fmin, double fmax, - double threshDb = Default_FundamentalEnv_ThreshDb, - double threshHz = Default_FundamentalEnv_ThreshHz ); - - - //! Return the fundamental frequency estimate envelope constructed - //! during the most recent analysis performed by this Analyzer. - //! - //! By default, a fundamental envelope is estimated during analysis - //! between the frequency resolution and 1.5 times the resolution. - const LinearEnvelope & fundamentalEnv( void ) const; - - //! Return the overall amplitude estimate envelope constructed - //! during the most recent analysis performed by this Analyzer. - const LinearEnvelope & ampEnv( void ) const; - - -// -- legacy support -- - - // Fundamental and amplitude envelopes are always constructed during - // analysis, these members do nothing, and are retained for backwards - // compatibility. - void buildAmpEnv( bool TF = true ) { TF = TF; } - void buildFundamentalEnv( bool TF = true ) { TF = TF; } - -// -- private member variables -- - -private: - - std::auto_ptr< Envelope > m_freqResolutionEnv; - //! in Hz, minimum instantaneous frequency distance; - //! this is the core parameter, others are, by default, - //! computed from this one - - double m_ampFloor; //! dB, relative to full amplitude sine wave, absolute - //! amplitude threshold (negative) - - double m_windowWidth; //! in Hz, width of main lobe; this might be more - //! conveniently presented as window length, but - //! the main lobe width more explicitly highlights - //! the critical interaction with resolution - - // std::auto_ptr< Envelope > m_freqFloorEnv; - double m_freqFloor; //! lowest frequency (Hz) component extracted - //! in spectral analysis - - double m_freqDrift; //! the maximum frequency (Hz) difference between two - //! consecutive Breakpoints that will be linked to - //! form a Partial - - double m_hopTime; //! in seconds, time between analysis windows in - //! successive spectral analyses - - double m_cropTime; //! in seconds, maximum time correction for a spectral - //! component to be considered reliable, and to be eligible - //! for extraction and for Breakpoint formation - - double m_bwAssocParam; //! formerly, width in Hz of overlapping bandwidth - //! association regions, or zero if bandwidth association - //! is disabled, now a catch-all bandwidth association - //! parameter that, if negative, indicates the tolerance (%) - //! level used to construct bandwidth envelopes from the - //! mixed phase derivative indicator - - double m_sidelobeLevel; //! sidelobe attenutation level for the Kaiser analysis - //! window, in positive dB - - bool m_phaseCorrect; //! flag indicating that phases/frequencies should be - //! made consistent at the end of the analysis - - PartialList m_partials; //! collect Partials here - - //! builder object for constructing a fundamental frequency - //! estimate during analysis - std::auto_ptr< LinearEnvelopeBuilder > m_f0Builder; - - //! builder object for constructing an amplitude - //! estimate during analysis - std::auto_ptr< LinearEnvelopeBuilder > m_ampEnvBuilder; - -// -- private auxiliary functions -- -// future development -/* - - // These members make up the sequence of operations in an - // analysis. If analysis were ever to be made into a - // template method, these would be the operations that - // derived classes could override. Or each of these could - // be represented by a strategy class. - - //! Compute the spectrum of the next sequence of samples. - void computeSpectrum( void ); - - //! Identify and select the spectral components that will be - //! used to form Partials. - void selectPeaks( void ); - - //! Compute the bandwidth coefficients for the Breakpoints - //! that are going to be used to form Partials. - void associateBandwidth( void ); - - //! Construct Partials from extracted spectral components. - //! Partials are built up frame by frame by appending - //! Breakpoints to Partials under construction, and giving - //! birth to new Partials using unmatched Peaks. - void formPartials( Peaks & peaks ); -*/ - // Reject peaks that are too close in frequency to a louder peak that is - // being retained, and peaks that are too quiet. Peaks that are retained, - // but are quiet enough to be in the specified fadeRange should be faded. - // - // Rejected peaks are placed at the end of the peak collection. - // Return the first position in the collection containing a rejected peak, - // or the end of the collection if no peaks are rejected. - Peaks::iterator thinPeaks( Peaks & peaks, double frameTime ); - - // Fix the bandwidth value stored in the specified Peaks. - // This function is invoked if the spectral residue method is - // not used to compute bandwidth (that method overwrites the - // bandwidth already). If the convergence method is used to - // compute bandwidth, the appropriate scaling is applied - // to the stored mixed phase derivative. Otherwise, the - // Peak bandwidth is set to zero. - void fixBandwidth( Peaks & peaks ); - -}; // end of class Analyzer - -} // end of namespace Loris - -#endif /* ndef INCLUDE_ANALYZER_H */ diff --git a/loris_library/Source/include/loris/AssociateBandwidth.h b/loris_library/Source/include/loris/AssociateBandwidth.h deleted file mode 100644 index 475aeb0..0000000 --- a/loris_library/Source/include/loris/AssociateBandwidth.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef INCLUDE_ASSOCIATEBANDWIDTH_H -#define INCLUDE_ASSOCIATEBANDWIDTH_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * AssociateBandwidth.h - * - * Definition of a class representing a policy for associating noise - * (bandwidth) energy with reassigned spectral peaks to be used in - * Partial formation. - * - * Kelly Fitz, 20 Jan 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "SpectralPeaks.h" - -#include - -// begin namespace -namespace Loris { - -class Breakpoint; - -// --------------------------------------------------------------------------- -// class AssociateBandwidth -// -// In the new strategy, Breakpoints are extracted and accumulated -// as sinusoids. Spectral peaks that are not extracted (don't exceed -// the amplitude floor) or are rejected for certain reasons, are -// accumulated diectly as noise (surplus). After all spectral peaks -// have been accumulated as noise or sinusoids, the noise is distributed -// as bandwidth. -// -class AssociateBandwidth -{ -// -- instance variables -- - std::vector< double > _weights; // weights vector for recording - // frequency distribution of retained - // sinusoids - std::vector< double > _surplus; // surplus (noise) energy vector for - // accumulating the distribution of - // spectral energy to be distributed - // as noise - - double _regionRate; // inverse of region center spacing - -// -- public interface -- -public: - // construction: - AssociateBandwidth( double regionWidth, double srate ); - ~AssociateBandwidth( void ); - - // Perform bandwidth association on a collection of reassigned spectral peaks - // or ridges. The range [begin, rejected) spans the Peaks selected to form - // Partials. The range [rejected, end) spans the Peaks that were found in - // the reassigned spectrum, but rejected as too weak or too close (in - // frequency) to another stronger Peak. - void associateBandwidth( Peaks::iterator begin, // beginning of Peaks - Peaks::iterator rejected, // first rejected Peak - Peaks::iterator end ); // end of Peaks - - -// -- private helpers -- -private: - double computeNoiseEnergy( double freq, double amp ); - - // These four formerly comprised the public interface - // to this policy, now they are all hidden behind a - // single call to associateBandwidth. - - // energy accumulation: - void accumulateNoise( double freq, double amp ); - void accumulateSinusoid( double freq, double amp ); - - // bandwidth assocation: - void associate( SpectralPeak & pk ); - - // call this to wipe out the accumulated energy to - // prepare for the next frame (yuk): - void reset( void ); - -}; // end of class AssociateBandwidth - -} // end of namespace Loris - -#endif /* ndef INCLUDE_ASSOCIATEBANDWIDTH_H */ diff --git a/loris_library/Source/include/loris/BigEndian.h b/loris_library/Source/include/loris/BigEndian.h deleted file mode 100644 index d4d70e8..0000000 --- a/loris_library/Source/include/loris/BigEndian.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef INCLUDE_BIGENDIAN_H -#define INCLUDE_BIGENDIAN_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * BigEndian.h - * - * Definition of wrappers for stream-based binary file i/o. - * - * Kelly Fitz, 23 May 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class BigEndian -// -class BigEndian -{ -public: - static std::istream & read( std::istream & s, long howmany, int size, char * putemHere ); - static std::ostream & write( std::ostream & s, long howmany, int size, const char * stuff ); -}; // end of class BigEndian - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_BIGENDIAN_H */ diff --git a/loris_library/Source/include/loris/Breakpoint.h b/loris_library/Source/include/loris/Breakpoint.h deleted file mode 100644 index 31123dd..0000000 --- a/loris_library/Source/include/loris/Breakpoint.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef INCLUDE_BREAKPOINT_H -#define INCLUDE_BREAKPOINT_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Breakpoint.h - * - * Definition of class Loris::Breakpoint. - * - * Kelly Fitz, 16 Aug 99 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// class Breakpoint -// -//! Class Breakpoint represents a single breakpoint in the -//! Partial parameter (frequency, amplitude, bandwidth) envelope. -//! Instantaneous phase is also stored, but is only used at the onset of -//! a partial, or when it makes a transition from zero to nonzero amplitude. -//! -//! Loris Partials represent reassigned bandwidth-enhanced model components. -//! A Partial consists of a chain of Breakpoints describing the time-varying -//! frequency, amplitude, and bandwidth (noisiness) of the component. -//! For more information about Reassigned Bandwidth-Enhanced -//! Analysis and the Reassigned Bandwidth-Enhanced Additive Sound -//! Model, refer to the Loris website: -//! www.cerlsoundgroup.org/Loris/. -//! -//! Breakpoint is a leaf class, do not subclass. -// -class Breakpoint -{ -// -- instance variables -- - double _frequency; //! in Hertz - double _amplitude; //! absolute - double _bandwidth; //! fraction of total energy that is noise energy - double _phase; //! radians - -// -- public Breakpoint interface -- - -public: -// -- construction -- - - //! Construct a new Breakpoint with all parameters initialized to 0 - //! (needed for STL containability). - Breakpoint( void ); - - //! Construct a new Breakpoint with the specified parameters. - //! - //! \param f is the intial frequency. - //! \param a is the initial amplitude. - //! \param b is the initial bandwidth. - //! \param p is the initial phase, if specified (if unspecified, 0 - //! is assumed). - Breakpoint( double f, double a, double b, double p = 0. ); - - // (use compiler-generated destructor, copy, and assign) - -// -- access -- - //! Return the amplitude of this Breakpoint. - double amplitude( void ) const { return _amplitude; } - - //! Return the bandwidth (noisiness) coefficient of this Breakpoint. - double bandwidth( void ) const { return _bandwidth; } - - //! Return the frequency of this Breakpoint. - double frequency( void ) const { return _frequency; } - - //! Return the phase of this Breakpoint. - double phase( void ) const { return _phase; } - -// -- mutation -- - //! Set the amplitude of this Breakpoint. - //! - //! \param x is the new amplitude - void setAmplitude( double x ) { _amplitude = x; } - - //! Set the bandwidth (noisiness) coefficient of this Breakpoint. - //! - //! \param x is the new bandwidth - void setBandwidth( double x ) { _bandwidth = x; } - - //! Set the frequency of this Breakpoint. - //! - //! \param x is the new frequency. - void setFrequency( double x ) { _frequency = x; } - - //! Set the phase of this Breakpoint. - //! - //! \param x is the new phase. - void setPhase( double x ) { _phase = x; } - - //! Add noise (bandwidth) energy to this Breakpoint by computing new - //! amplitude and bandwidth values. enoise may be negative, but - //! noise energy cannot be removed (negative energy added) in excess - //! of the current noise energy. - //! - //! \param enoise is the amount of noise energy to add to - //! this Breakpoint. - void addNoiseEnergy( double enoise ); - -}; // end of class Breakpoint - -} // end of namespace Loris - -#endif /* ndef INCLUDE_BREAKPOINT_H */ diff --git a/loris_library/Source/include/loris/BreakpointEnvelope.h b/loris_library/Source/include/loris/BreakpointEnvelope.h deleted file mode 100644 index 383626a..0000000 --- a/loris_library/Source/include/loris/BreakpointEnvelope.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef INCLUDE_BREAKPOINTENVELOPE_H -#define INCLUDE_BREAKPOINTENVELOPE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * BreakpointEnvelope.h - * - * Definition of class BreakpointEnvelope. - * This class has been renamed LinearEnvelope. The old - * name and header are preserved for compatibility. - * - * Kelly Fitz, 21 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "LinearEnvelope.h" - -// begin namespace -namespace Loris { - - typedef LinearEnvelope BreakpointEnvelope; - -} - -#endif /* ndef INCLUDE_BREAKPOINTENVELOPE_H */ diff --git a/loris_library/Source/include/loris/BreakpointUtils.h b/loris_library/Source/include/loris/BreakpointUtils.h deleted file mode 100644 index 41fd106..0000000 --- a/loris_library/Source/include/loris/BreakpointUtils.h +++ /dev/null @@ -1,217 +0,0 @@ -#ifndef INCLUDE_BREAKPOINTUTILS_H -#define INCLUDE_BREAKPOINTUTILS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * BreakpointUtils.h - * - * Breakpoint utility functions collected in namespace BreakpointUtils. - * - * Kelly Fitz, 6 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Breakpoint.h" -#include -#include - -// begin namespace -namespace Loris { - -namespace BreakpointUtils { - -// -- free functions -- - -// --------------------------------------------------------------------------- -// addNoiseEnergy -// --------------------------------------------------------------------------- -//! Add noise (bandwidth) energy to a Breakpoint by computing new -//! amplitude and bandwidth values. enoise may be negative, but -//! noise energy cannot be removed (negative energy added) in excess -//! of the current noise energy. -//! -//! \deprecated This operation is now part of the Breakpoint interface. -//! Use Breakpoint::addNoiseEnergy instead. -// -inline void addNoiseEnergy( Breakpoint & bp, double enoise ) -{ - bp.addNoiseEnergy(enoise); -} - -// --------------------------------------------------------------------------- -// makeNullBefore -// --------------------------------------------------------------------------- -//! Return a null (zero-amplitude) Breakpoint to preceed the specified -//! Breakpoint, useful for fading in a Partial. -//! -//! \param bp make a null Breakpoint to preceed this one -//! \param fadeTime the time (in seconds) by which the new null Breakpoint -//! should preceed bp -//! \return a new null Breakpoint, having zero amplitude, frequency equal -//! to that of bp, and phase computed back from that of bp -// -Breakpoint makeNullBefore( const Breakpoint & bp, double fadeTime ); // see BreakpointUtils.C - - -// --------------------------------------------------------------------------- -// addNoiseEnergy -// --------------------------------------------------------------------------- -//! Return a null (zero-amplitude) Breakpoint to succeed the specified -//! Breakpoint, useful for fading out a Partial. -//! -//! \param bp make a null Breakpoint to succeed this one -//! \param fadeTime the time (in seconds) by which the new null Breakpoint -//! should succeed bp -//! \return a new null Breakpoint, having zero amplitude, frequency equal -//! to that of bp, and phase computed forward from that of bp -// -Breakpoint makeNullAfter( const Breakpoint & bp, double fadeTime ); // see BreakpointUtils.C - -// -- predicates -- - -// --------------------------------------------------------------------------- -// isFrequencyBetween -// -//! Predicate functor returning true if its Breakpoint argument -//! has frequency between specified bounds, and false otherwise. -// -class isFrequencyBetween : - public std::unary_function< const Breakpoint, bool > -{ -public: - //! Return true if its Breakpoint argument has frequency - //! between specified bounds, and false otherwise. - bool operator()( const Breakpoint & b ) const - { - return (b.frequency() > _fmin) && - (b.frequency() < _fmax); - } - -// constructor: - - //! Construct a predicate functor, specifying two frequency bounds. - isFrequencyBetween( double x, double y ) : - _fmin( x ), _fmax( y ) - { - if (x>y) std::swap(x,y); - } - -// bounds: -private: - double _fmin, _fmax; -}; - -//! Old name for isFrequencyBetween. -//! \deprecated use isFrequencyBetween instead. -typedef isFrequencyBetween frequency_between; - -// --------------------------------------------------------------------------- -// isNonNull -// -//! Predicate functor returning true if a Breakpoint has non-zero -//! amplitude, false otherwise. -// -static bool isNonNull( const Breakpoint & bp ) -{ - return bp.amplitude() != 0.; -} - -// --------------------------------------------------------------------------- -// isNull -// -//! Predicate functor returning true if a Breakpoint has zero -//! amplitude, false otherwise. -// -static bool isNull( const Breakpoint & bp ) -{ - return ! isNonNull( bp ); -} - -// -- comparitors -- - -// --------------------------------------------------------------------------- -// compareFrequencyLess -// -//! Comparitor (binary) functor returning true if its first Breakpoint -//! argument has frequency less than that of its second Breakpoint argument, -//! and false otherwise. -// -class compareFrequencyLess : - public std::binary_function< const Breakpoint, const Breakpoint, bool > -{ -public: - //! Return true if its first Breakpoint argument has frequency less - //! than that of its second Breakpoint argument, and false otherwise. - bool operator()( const Breakpoint & lhs, const Breakpoint & rhs ) const - { return lhs.frequency() < rhs.frequency(); } -}; - -//! Old name for compareFrequencyLess. -//! \deprecated use compareFrequencyLess instead. -typedef compareFrequencyLess less_frequency; - -// --------------------------------------------------------------------------- -// compareAmplitudeGreater -// -//! Comparitor (binary) functor returning true if its first Breakpoint -//! argument has amplitude greater than that of its second Breakpoint argument, -//! and false otherwise. -// -class compareAmplitudeGreater : - public std::binary_function< const Breakpoint, const Breakpoint, bool > -{ -public: - //! Return true if its first Breakpoint argument has amplitude greater - //! than that of its second Breakpoint argument, and false otherwise. - bool operator()( const Breakpoint & lhs, const Breakpoint & rhs ) const - { return lhs.amplitude() > rhs.amplitude(); } -}; - -//! Old name for compareAmplitudeGreater. -//! \deprecated use compareAmplitudeGreater instead. -typedef compareAmplitudeGreater greater_amplitude; - -// --------------------------------------------------------------------------- -// compareAmplitudeLess -// -//! Comparitor (binary) functor returning true if its first Breakpoint -//! argument has amplitude less than that of its second Breakpoint argument, -//! and false otherwise. -// -class compareAmplitudeLess : - public std::binary_function< const Breakpoint, const Breakpoint, bool > -{ -public: - //! Return true if its first Breakpoint argument has amplitude greater - //! than that of its second Breakpoint argument, and false otherwise. - bool operator()( const Breakpoint & lhs, const Breakpoint & rhs ) const - { return lhs.amplitude() < rhs.amplitude(); } -}; - -} // end of namespace BreakpointUtils - -} // end of namespace Loris - -#endif /* ndef INCLUDE_BREAKPOINTUTILS_H */ diff --git a/loris_library/Source/include/loris/Channelizer.h b/loris_library/Source/include/loris/Channelizer.h deleted file mode 100644 index d57932b..0000000 --- a/loris_library/Source/include/loris/Channelizer.h +++ /dev/null @@ -1,526 +0,0 @@ -#ifndef INCLUDE_CHANNELIZER_H -#define INCLUDE_CHANNELIZER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Channelizer.h - * - * Definition of class Loris::Channelizer. - * - * Kelly Fitz, 21 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "PartialList.h" - -#include - -// begin namespace -namespace Loris { - -class Envelope; -class Partial; - -// --------------------------------------------------------------------------- -// Channelizer -// -//! Class Channelizer represents an algorithm for automatic labeling of -//! a sequence of Partials. Partials must be labeled in -//! preparation for morphing (see Morpher) to establish correspondences -//! between Partials in the morph source and target sounds. -//! -//! Channelized partials are labeled according to their adherence to a -//! harmonic frequency structure with a time-varying fundamental -//! frequency. The frequency spectrum is partitioned into -//! non-overlapping channels having time-varying center frequencies that -//! are harmonic (integer) multiples of a specified reference frequency -//! envelope, and each channel is identified by a unique label equal to -//! its harmonic number. Each Partial is assigned the label -//! corresponding to the channel containing the greatest portion of its -//! (the Partial's) energy. -//! -//! A reference frequency Envelope for channelization and the channel -//! number to which it corresponds (1 for an Envelope that tracks the -//! Partial at the fundamental frequency) must be specified. The -//! reference Envelope can be constructed explcitly, point by point -//! (using, for example, the BreakpointEnvelope class), or constructed -//! automatically using the FrequencyReference class. -//! -//! The Channelizer can be configured with a stretch factor, to accomodate -//! detuned harmonics, as in the case of piano tones. The static member -//! computeStretchFactor can compute the apppropriate stretch factor, given -//! a pair of partials. This computation is based on formulae given in -//! "Understanding the complex nature of the piano tone" by Martin Keane -//! at the Acoustics Research Centre at the University of Aukland (Feb 2004). -//! The stretching factor must be non-negative (and is zero for perfectly -//! tunes harmonics). Even in the case of stretched harmonics, the -//! reference frequency envelope is assumed to track the frequency of -//! one of the partials, and the center frequency of the corresponding -//! channel, even though it may represent a stretched harmonic. -//! -//! Channelizer is a leaf class, do not subclass. -// -class Channelizer -{ -// -- implementaion -- - std::auto_ptr< Envelope > _refChannelFreq; //! the reference frequency envelope - - int _refChannelLabel; //! the channel number corresponding to the - //! reference frequency (1 for the fundamental) - - double _stretchFactor; //! stretching factor to account for - //! detuned harmonics, as in the case of the piano; - //! can be computed using the static member - //! computeStretchFactor. Should be 0 for most - //! (strongly harmonic) sounds. - - double _ampWeighting; //! exponent for amplitude weighting in channel - //! computation, 0 for no weighting, 1 for linear - //! amplitude weighting, 2 for power weighting, etc. - //! default is 0, amplitude weighting is a bad idea - //! for many sounds - -// -- public interface -- -public: -// -- construction -- - - //! Construct a new Channelizer using the specified reference - //! Envelope to represent the a numbered channel. If the sound - //! being channelized is known to have detuned harmonics, a - //! stretching factor can be specified (defaults to 0 for no - //! stretching). The stretching factor can be computed using - //! the static member computeStretchFactor. - //! - //! \param refChanFreq is an Envelope representing the center frequency - //! of a channel. - //! \param refChanLabel is the corresponding channel number (i.e. 1 - //! if refChanFreq is the lowest-frequency channel, and all - //! other channels are harmonics of refChanFreq, or 2 if - //! refChanFreq tracks the second harmonic, etc.). - //! \param stretchFactor is a stretching factor to account for detuned - //! harmonics, default is 0. - //! - //! \throw InvalidArgument if refChanLabel is not positive. - //! \throw InvalidArgument if stretchFactor is negative. - Channelizer( const Envelope & refChanFreq, int refChanLabel, double stretchFactor = 0 ); - - //! Construct a new Channelizer having a constant reference frequency. - //! The specified frequency is the center frequency of the lowest-frequency - //! channel (for a harmonic sound, the channel containing the fundamental - //! Partial. - //! - //! \param refFreq is the reference frequency (in Hz) corresponding - //! to the first frequency channel. - //! \param stretchFactor is a stretching factor to account for detuned - //! harmonics, default is 0. - //! - //! \throw InvalidArgument if refChanLabel is not positive. - //! \throw InvalidArgument if stretchFactor is negative. - Channelizer( double refFreq, double stretchFactor = 0 ); - - //! Construct a new Channelizer that is an exact copy of another. - //! The copy represents the same set of frequency channels, constructed - //! from the same reference Envelope and channel number. - //! - //! \param other is the Channelizer to copy - Channelizer( const Channelizer & other ); - - //! Assignment operator: make this Channelizer an exact copy of another. - //! This Channelizer is made to represent the same set of frequency channels, - //! constructed from the same reference Envelope and channel number as rhs. - //! - //! \param rhs is the Channelizer to copy - Channelizer & operator=( const Channelizer & rhs ); - - //! Destroy this Channelizer. - ~Channelizer( void ); - -// -- channelizing -- - - //! Label a Partial with the number of the frequency channel containing - //! the greatest portion of its (the Partial's) energy. - //! - //! \param partial is the Partial to label. - void channelize( Partial & partial ) const; - - //! Assign each Partial in the specified half-open (STL-style) range - //! the label corresponding to the frequency channel containing the - //! greatest portion of its (the Partial's) energy. - //! - //! \param begin is the beginning of the range of Partials to channelize - //! \param end is (one-past) the end of the range of Partials to channelize - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void channelize( Iter begin, Iter end ) const; -#else - void channelize( PartialList::iterator begin, PartialList::iterator end ) const; -#endif - - //! Function call operator: same as channelize(). -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void operator() ( Iter begin, Iter end ) const -#else - inline - void operator() ( PartialList::iterator begin, PartialList::iterator end ) const -#endif - { channelize( begin, end ); } - - //! Compute the center frequency of one a channel at the specified - //! time. For non-stretched harmonics, this is simply the value - //! of the reference envelope scaled by the ratio of the specified - //! channel number to the reference channel number. For stretched - //! harmonics, the channel center frequency is computed using the - //! stretch factor. See Martin Keane, "Understanding - //! the complex nature of the piano tone", 2004, for a discussion - //! and the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! \param time is the time (in seconds) at which to evalute - //! the reference envelope - //! \param channel is the frequency channel (or harmonic, or vibrational - //! mode) number whose frequency is to be determined - //! \return the center frequency in Hz of the specified frequency channel - //! at the specified time - double channelFrequencyAt( double time, int channel ) const; - - //! Compute the (fractional) channel number estimate for a Partial having a - //! given frequency at a specified time. For ordinary harmonics, this - //! is simply the ratio of the specified frequency to the reference - //! frequency at the specified time. For stretched harmonics (as in - //! a piano), the stretching factor is used to compute the frequency - //! of the corresponding modes of a massy string. See Martin Keane, - //! "Understanding the complex nature of the piano tone", 2004, for - //! the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! \param time is the time (in seconds) at which to evalute - //! the reference envelope - //! \param frequency is the frequency (in Hz) for wihch the channel - //! number is to be determined - //! \return the channel number corresponding to the specified - //! frequency and time - int computeChannelNumber( double time, double frequency ) const; - - //! Compute the (fractional) channel number estimate for a Partial having a - //! given frequency at a specified time. For ordinary harmonics, this - //! is simply the ratio of the specified frequency to the reference - //! frequency at the specified time. For stretched harmonics (as in - //! a piano), the stretching factor is used to compute the frequency - //! of the corresponding modes of a massy string. See Martin Keane, - //! "Understanding the complex nature of the piano tone", 2004, for - //! the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! The fractional channel number is used internally to determine - //! a best estimate for the channel number (label) for a Partial - //! having time-varying frequency. - //! - //! \param time is the time (in seconds) at which to evalute - //! the reference envelope - //! \param frequency is the frequency (in Hz) for wihch the channel - //! number is to be determined - //! \return the fractional channel number corresponding to the specified - //! frequency and time - double computeFractionalChannelNumber( double time, double frequency ) const; - - - //! Compute the reference frequency at the specified time. For non-stretched - //! harmonics, this is simply the ratio of the reference envelope evaluated - //! at that time to the reference channel number, and is the center frequecy - //! for the lowest channel. For stretched harmonics, the reference frequency - //! is NOT equal to the center frequency of any of the channels, and is also - //! a function of the stretch factor. - //! - //! \param time is the time (in seconds) at which to evalute - //! the reference envelope - double referenceFrequencyAt( double time ) const; - -// -- access/mutation -- - - //! Return the exponent applied to amplitude before weighting - //! the instantaneous estimate of the frequency channel number - //! for a Partial. zero (default) for no weighting, 1 for linear - //! amplitude weighting, 2 for power weighting, etc. - //! Amplitude weighting is a bad idea for many sounds, particularly - //! those with transients, for which it may emphasize the part of - //! the Partial having the least reliable frequency estimate. - double amplitudeWeighting( void ) const; - - //! Set the exponent applied to amplitude before weighting - //! the instantaneous estimate of the frequency channel number - //! for a Partial. zero (default) for no weighting, 1 for linear - //! amplitude weighting, 2 for power weighting, etc. - //! Amplitude weighting is a bad idea for many sounds, particularly - //! those with transients, for which it may emphasize the part of - //! the Partial having the least reliable frequency estimate. - void setAmplitudeWeighting( double expon ); - - //! Return the stretching factor used to account for detuned - //! harmonics, as in a piano tone. Normally set to 0 for - //! in-tune harmonics. - //! - //! The stretching factor is a small positive number for - //! heavy vibrating strings (as in pianos) for which the - //! mass of the string significantly affects the frequency - //! of the vibrating modes. See Martin Keane, "Understanding - //! the complex nature of the piano tone", 2004, for a discussion - //! and the source of the mode frequency stretching algorithms - //! implemented here. - double stretchFactor( void ) const; - - //! Set the stretching factor used to account for detuned - //! harmonics, as in a piano tone. Normally set to 0 for - //! in-tune harmonics. The stretching factor for massy - //! vibrating strings (like pianos) can be computed from - //! the physical characteristics of the string, or using - //! computeStretchFactor(). - //! - //! The stretching factor is a small positive number for - //! heavy vibrating strings (as in pianos) for which the - //! mass of the string significantly affects the frequency - //! of the vibrating modes. See Martin Keane, "Understanding - //! the complex nature of the piano tone", 2004, for a discussion - //! and the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! \throw InvalidArgument if stretch is negative. - void setStretchFactor( double stretch ); - - -// -- static members -- - - - //! Static member to compute the stretch factor for a sound having - //! (consistently) detuned harmonics, like piano tones. - //! - //! The stretching factor is a small positive number for - //! heavy vibrating strings (as in pianos) for which the - //! mass of the string significantly affects the frequency - //! of the vibrating modes. See Martin Keane, "Understanding - //! the complex nature of the piano tone", 2004, for a discussion - //! and the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! The value returned by this function MAY NOT be a valid stretch - //! factor. If this function returns a negative stretch factor, - //! then the specified pair of frequencies and mode numbers cannot - //! be used to estimate the effects of string mass on mode frequency - //! (because the negative stretch factor implies a physical - //! impossibility, like negative mass or negative length). - //! - //! \param fm is the frequency of the Mth stretched harmonic - //! \param m is the harmonic number of the harmonic whose frequnecy is fm - //! \param fn is the frequency of the Nth stretched harmonic - //! \param n is the harmonic number of the harmonic whose frequnecy is fn - //! \returns the stretching factor, usually a very small positive - //! floating point number, or 0 for pefectly tuned harmonics - //! (that is, if fn = n*f1). - static double computeStretchFactor( double fm, int m, double fn, int n ); - - -// -- simplified interface -- - - //! Static member that constructs an instance and applies - //! it to a PartialList (simplified interface). - //! - //! Construct a Channelizer using the specified Envelope - //! and reference label, and use it to channelize a - //! sequence of Partials. - //! - //! \param partials is the sequence of Partials to - //! channelize. - //! \param refChanFreq is an Envelope representing the center frequency - //! of a channel. - //! \param refChanLabel is the corresponding channel number (i.e. 1 - //! if refChanFreq is the lowest-frequency channel, and all - //! other channels are harmonics of refChanFreq, or 2 if - //! refChanFreq tracks the second harmonic, etc.). - //! \throw InvalidArgument if refChanLabel is not positive. - static - void channelize( PartialList & partials, - const Envelope & refChanFreq, int refChanLabel ); - - - -// -- DEPRECATED members -- - - //! DEPRECATED - //! - //! Set the stretching factor used to account for (consistently) - //! detuned harmonics, as in a piano tone, from a pair of - //! mode (harmonic) frequencies and numbers. - //! - //! The stretching factor is a small positive number for - //! heavy vibrating strings (as in pianos) for which the - //! mass of the string significantly affects the frequency - //! of the vibrating modes. See Martin Keane, "Understanding - //! the complex nature of the piano tone", 2004, for a discussion - //! and the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! The stretching factor is computed using computeStretchFactor, - //! but only a valid stretch factor will ever be assigned. If an - //! invalid (negative) stretching factor is computed for the - //! specified frequencies and mode numbers, the stretch factor - //! will be set to zero. - //! - //! \param fm is the frequency of the Mth stretched harmonic - //! \param m is the harmonic number of the harmonic whose frequnecy is fm - //! \param fn is the frequency of the Nth stretched harmonic - //! \param n is the harmonic number of the harmonic whose frequnecy is fn - void setStretchFactor( double fm, int m, double fn, int n ); - - - //! DEPRECATED - //! - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Channelizer using the specified Envelope - //! and reference label, and use it to channelize a - //! sequence of Partials. - //! - //! \param begin is the beginning of a sequence of Partials to - //! channelize. - //! \param end is the end of a sequence of Partials to - //! channelize. - //! \param refChanFreq is an Envelope representing the center frequency - //! of a channel. - //! \param refChanLabel is the corresponding channel number (i.e. 1 - //! if refChanFreq is the lowest-frequency channel, and all - //! other channels are harmonics of refChanFreq, or 2 if - //! refChanFreq tracks the second harmonic, etc.). - //! \throw InvalidArgument if refChanLabel is not positive. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - static - void channelize( Iter begin, Iter end, - const Envelope & refChanFreq, int refChanLabel ); -#else - static inline - void channelize( PartialList::iterator begin, PartialList::iterator end, - const Envelope & refChanFreq, int refChanLabel ); -#endif - - - //! DEPRECATED - //! - //! Static member to compute the stretch factor for a sound having - //! (consistently) detuned harmonics, like piano tones. Legacy version - //! that assumes the first argument corresponds to the first partial. - //! - //! \param f1 is the frequency of the lowest numbered (1) partial. - //! \param fn is the frequency of the Nth stretched harmonic - //! \param n is the harmonic number of the harmonic whose frequnecy is fn - //! \returns the stretching factor, usually a very small positive - //! floating point number, or 0 for pefectly tuned harmonics - //! (that is, for harmonic frequencies fn = n*f1). - static double computeStretchFactor( double f1, double fn, double n ); - -}; // end of class Channelizer - -// --------------------------------------------------------------------------- -// channelize (sequence of Partials) -// --------------------------------------------------------------------------- -//! Assign each Partial in the specified half-open (STL-style) range -//! the label corresponding to the frequency channel containing the -//! greatest portion of its (the Partial's) energy. -//! -//! \param begin is the beginning of the range of Partials to channelize -//! \param end is (one-past) the end of the range of Partials o channelize -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Channelizer::channelize( Iter begin, Iter end ) const -#else -inline -void Channelizer::channelize( PartialList::iterator begin, PartialList::iterator end ) const -#endif -{ - while ( begin != end ) - { - channelize( *begin++ ); - } -} - -// --------------------------------------------------------------------------- -// channelize (static) -// --------------------------------------------------------------------------- -//! DEPRECATED -//! -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! Construct a Channelizer using the specified Envelope -//! and reference label, and use it to channelize a -//! sequence of Partials. -//! -//! \param begin is the beginning of a sequence of Partials to -//! channelize. -//! \param end is the end of a sequence of Partials to -//! channelize. -//! \param refChanFreq is an Envelope representing the center frequency -//! of a channel. -//! \param refChanLabel is the corresponding channel number (i.e. 1 -//! if refChanFreq is the lowest-frequency channel, and all -//! other channels are harmonics of refChanFreq, or 2 if -//! refChanFreq tracks the second harmonic, etc.). -//! \throw InvalidArgument if refChanLabel is not positive. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Channelizer::channelize( Iter begin, Iter end, - const Envelope & refChanFreq, int refChanLabel ) -#else -inline -void Channelizer::channelize( PartialList::iterator begin, PartialList::iterator end, - const Envelope & refChanFreq, int refChanLabel ) -#endif -{ - Channelizer instance( refChanFreq, refChanLabel ); - while ( begin != end ) - { - instance.channelize( *begin++ ); - } -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_CHANNELIZER_H */ diff --git a/loris_library/Source/include/loris/Collator.h b/loris_library/Source/include/loris/Collator.h deleted file mode 100644 index e1d441c..0000000 --- a/loris_library/Source/include/loris/Collator.h +++ /dev/null @@ -1,366 +0,0 @@ -#ifndef INCLUDE_COLLATOR_H -#define INCLUDE_COLLATOR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Collator.h - * - * Definition of class Collator. - * - * Kelly Fitz, 29 April 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Distiller.h" // for default fade time and silent time -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Collator -// -//! Class Collator represents an algorithm for reducing a collection -//! of Partials into the smallest collection of "equivalent" Partials -//! by joining non-overlapping Partials end to end. -//! -//! Partials that are not labeled, that is, Partials having label 0, -//! are "collated " into groups of non-overlapping (in time) -//! Partials, and fused into a single Partial per group. -//! "Collating" is a bit like "distilling" but non-overlapping -//! Partials are grouped without regard to frequency proximity. This -//! algorithm produces the smallest-possible number of collated Partials. -//! Thanks to Ulrike Axen for providing this optimal algorithm. -//! -//! Collating modifies the Partial container (a PartialList). Only -//! unlabeled (labeled 0) Partials are affected by the collating -//! operation. Collated Partials are moved to the end of the -//! collection of Partials. -// -class Collator -{ -// -- instance variables -- - - double _fadeTime, _gapTime; - -// -- public interface -- -public: - -// -- global defaults and constants -- - - enum - { - - //! Default time in milliseconds over which Partials joined by - //! distillation fade to and from zero amplitude. Divide by - //! 1000 to use as a member function parameter. This parameter - //! should be the same in Distiller, Sieve, and Collator. - DefaultFadeTimeMs = Distiller::DefaultFadeTimeMs, - - //! Default minimum duration in milliseconds of the silent - //! (zero-amplitude) gap between two Partials joined by - //! distillation. Divide by 1000 to use as a member function - //! parameter. This parameter should be the same in Distiller, - //! Sieve, and Collator. - DefaultSilentTimeMs = Distiller::DefaultSilentTimeMs - }; - -// -- construction -- - - //! Construct a new Collator using the specified fade and gap times - //! between Partials. When two Partials are joined, the collated Partial - //! fades out at the end of the earlier Partial and back in again - //! at the onset of the later one. The fade time is the time over - //! which these fades occur. By default, use a 5 ms fade time. - //! The gap time is the additional time over which a Partial faded - //! out must remain at zero amplitude before it can fade back in. - //! By default, use a gap time of one millisecond, to - //! prevent a pair of arbitrarily close null Breakpoints being - //! inserted. (Defaults are copied from the Distiller.) - //! - //! \param partialFadeTime is the time (in seconds) over - //! which Partials joined by distillation fade to - //! and from zero amplitude. Default is 0.005 (one - //! millisecond). - //! \param partialSilentTime is the minimum duration (in seconds) - //! of the silent (zero-amplitude) gap between two - //! Partials joined by distillation. (Default is - //! 0.001 (one millisecond). - explicit - Collator( double partialFadeTime = Collator::DefaultFadeTimeMs/1000.0, - double partialSilentTime = Collator::DefaultSilentTimeMs/1000.0 ); - - // Use compiler-generated copy, assign, and destroy. - -// -- collating -- - - //! Collate unlabeled (zero-labeled) Partials into the smallest-possible - //! number of Partials that does not combine any overlapping Partials. - //! Collated Partials assigned labels higher than any label in the original - //! list, and appear at the end of the sequence, after all previously-labeled - //! Partials. - //! - //! - //! Return an iterator refering to the position of the first collated Partial, - //! or the end of the collated collection if there are no collated Partials. - //! Since collating is in-place, the Partials collection may be smaller - //! (fewer Partials) after collating, and any iterators on the collection - //! may be invalidated. - //! - //! \param partials is the collection of Partials to collate in-place - //! \return the position of the end of the range of labeled Partials, - //! which is either the end of the collection, or the position - //! of the first collated Partial, composed of unlabeled Partials - //! in the original collection. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials - //! must be a PartialList, otherwise it can be any container type - //! storing Partials that supports at least bidirectional iterators. - //! - //! \sa Collator::collate( Container & partials ) -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - typename Container::iterator collate( Container & partials ); -#else - inline - PartialList::iterator collate( PartialList & partials ); -#endif - - //! Function call operator: same as collate( PartialList & partials ). -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - typename Container::iterator operator() ( Container & partials ); -#else - PartialList::iterator operator() ( PartialList & partials ); -#endif - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. Collated Partials are - //! labeled beginning with the label one more than the - //! largest label in the orignal Partials. - //! - //! \param partials is the collection of Partials to collate in-place - //! \param partialFadeTime is the time (in seconds) over - //! which Partials joined by collating fade to - //! and from zero amplitude. - //! \param partialSilentTime is the minimum duration (in seconds) - //! of the silent (zero-amplitude) gap between two - //! Partials joined by collating. - //! \return the position of the first collated Partial - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials - //! must be a PartialList, otherwise it can be any container type - //! storing Partials that supports at least bidirectional iterators. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - static typename Container::iterator - collate( Container & partials, double partialFadeTime, - double partialSilentTime ); -#else - static inline PartialList::iterator - collate( PartialList & partials, double partialFadeTime, - double partialSilentTime ); -#endif - - -private: - -// -- helpers -- - - //! Collate unlabeled (zero labeled) Partials into the smallest - //! possible number of Partials that does not combine any temporally - //! overlapping Partials. Give each collated Partial a label, starting - //! with startlabel, and incrementing. If startLabel is zero, then - //! give each collated Partial the label zero. The unlabeled Partials are - //! collated in-place. - void collateAux( PartialList & unlabled ); - -}; // end of class Collator - -// --------------------------------------------------------------------------- -// collate -// --------------------------------------------------------------------------- -//! Collate unlabeled (zero-labeled) Partials into the smallest-possible -//! number of Partials that does not combine any overlapping Partials. -//! Collated Partials assigned labels higher than any label in the original -//! list, and appear at the end of the sequence, after all previously-labeled -//! Partials. -//! -//! Return an iterator refering to the position of the first collated Partial, -//! or the end of the collated collection if there are no collated Partials. -//! Since collating is in-place, the Partials collection may be smaller -//! (fewer Partials) after collating, and any iterators on the collection -//! may be invalidated. -//! -//! \param partials is the collection of Partials to collate in-place -//! \return the position of the end of the range of labeled Partials, -//! which is either the end of the collection, or the position -//! of the first collated Partial, composed of unlabeled Partials -//! in the original collection. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then partials -//! must be a PartialList, otherwise it can be any container type -//! storing Partials that supports at least bidirectional iterators. -//! -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator -Collator::collate( Container & partials ) -#else -inline -PartialList::iterator -Collator::collate( PartialList & partials ) -#endif -{ -#if ! defined(NO_TEMPLATE_MEMBERS) - typedef typename Container::iterator Iterator; -#else - typedef PartialList::iterator Iterator; -#endif - - // Partition the Partials into labeled and unlabeled, - // and collate the unlabeled ones and replace the - // unlabeled range. - // (This requires bidirectional iterator support.) - Iterator beginUnlabeled = - std::partition( partials.begin(), partials.end(), - std::not1( PartialUtils::isLabelEqual(0) ) ); - // this used to be a stable partition, which - // is very much slower and seems unnecessary - - // cannot splice if this operation is to be generic - // with respect to container, have to copy: - PartialList collated( beginUnlabeled, partials.end() ); - // collated.splice( collated.end(), beginUnlabeled, partials.end() ); - - // determine the label for the first collated Partial: - Partial::label_type labelCollated = 1; - if ( partials.begin() != beginUnlabeled ) - { - labelCollated = - 1 + std::max_element( partials.begin(), beginUnlabeled, - PartialUtils::compareLabelLess() )->label(); - } - if ( labelCollated < 1 ) - { - labelCollated = 1; - } - - // collate unlabeled (zero-labeled) Partials: - collateAux( collated ); - - // label the collated Partials: - for ( Iterator it = collated.begin(); it != collated.end(); ++it ) - { - it->setLabel( labelCollated++ ); - } - - // copy the collated Partials back into the source container - // after the range of labeled Partials - Iterator endCollated = - std::copy( collated.begin(), collated.end(), beginUnlabeled ); - - // remove extra Partials from the end of the source container - if ( endCollated != partials.end() ) - { - typename Iterator::difference_type numLabeled = - std::distance( partials.begin(), beginUnlabeled ); - - partials.erase( endCollated, partials.end() ); - - // restore beginUnlabeled: - beginUnlabeled = partials.begin(); - std::advance( beginUnlabeled, numLabeled ); - } - return beginUnlabeled; -} - -// --------------------------------------------------------------------------- -// Function call operator -// --------------------------------------------------------------------------- -//! Function call operator: same as collate( PartialList & partials ). -//! -//! \sa Collator::collate( Container & partials ) -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator Collator::operator()( Container & partials ) -#else -inline -PartialList::iterator Collator::operator()( PartialList & partials ) -#endif -{ - return collate( partials ); -} - -// --------------------------------------------------------------------------- -// collate -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. Collated Partials are -//! labeled beginning with the label one more than the -//! largest label in the orignal Partials. -//! -//! \post All Partials in the collection are uniquely-labeled, -//! collated Partials are all at the end of the collection -//! (after all labeled Partials). -//! \param partials is the collection of Partials to collate in-place -//! \param partialFadeTime is the time (in seconds) over -//! which Partials joined by collating fade to -//! and from zero amplitude. -//! \param partialSilentTime is the minimum duration (in seconds) -//! of the silent (zero-amplitude) gap between two -//! Partials joined by collateation. (Default is -//! 0.0001 (one tenth of a millisecond). -//! \return the position of the first collated Partial -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then partials -//! must be a PartialList, otherwise it can be any container type -//! storing Partials that supports at least bidirectional iterators. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator -Collator::collate( Container & partials, double partialFadeTime, - double partialSilentTime ) -#else -inline -PartialList::iterator -Collator::collate( PartialList & partials, double partialFadeTime, - double partialSilentTime ) -#endif -{ - Collator instance( partialFadeTime, partialSilentTime ); - return instance.collate( partials ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_COLLATOR_H */ diff --git a/loris_library/Source/include/loris/Dilator.h b/loris_library/Source/include/loris/Dilator.h deleted file mode 100644 index 3370788..0000000 --- a/loris_library/Source/include/loris/Dilator.h +++ /dev/null @@ -1,410 +0,0 @@ -#ifndef INCLUDE_DILATOR_H -#define INCLUDE_DILATOR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Dilator.h - * - * Definition of class Dilator. - * - * Kelly Fitz, 26 Oct 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if defined(NO_TEMPLATE_MEMBERS) -#include "PartialList.h" -#endif - -#include - -// begin namespace -namespace Loris { - -class Marker; -class Partial; - -// --------------------------------------------------------------------------- -// class Dilator -// -//! Class Dilator represents an algorithm for non-uniformly expanding -//! and contracting the Partial parameter envelopes according to the initial -//! and target (desired) times of temporal features. -//! -//! It is frequently necessary to redistribute temporal events in this way -//! in preparation for a sound morph. For example, when morphing instrument -//! tones, it is common to align the attack, sustain, and release portions -//! of the source sounds by dilating or contracting those temporal regions. -//! -//! This same procedure can be applied to the Markers stored in AiffFile, -//! SdifFile, and SpcFile (see Marker.h). -// -class Dilator -{ -// -- instance variables -- - - std::vector< double > _initial, _target; // time points - -// -- public interface -- -public: -// -- construction -- - - //! Construct a new Dilator with no time points. - Dilator( void ); - - //! Construct a new Dilator using a range of initial time points - //! and a range of target (desired) time points. The client must - //! ensure that the target range has at least as many elements as - //! the initial range. - //! - //! \param ibegin is the beginning of a sequence of initial, or source, - //! time points. - //! \param iend is (one-past) the end of a sequence of initial, or - //! source, time points. - //! \param tbegin is the beginning of a sequence of target time points; - //! this sequence must be as long as the sequence of initial time - //! point described by ibegin and iend. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only const double * arguments. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - Dilator( Iter1 ibegin, Iter1 iend, Iter2 tbegin ); -#else - inline - Dilator( const double * ibegin, const double * iend, const double * tbegin ); -#endif - - // Use compiler-generated copy, assign, and destroy. - -// -- mutation -- - - //! Insert a pair of initial and target time points. - //! - //! Specify a pair of initial and target time points to be used - //! by this Dilator, corresponding, for example, to the initial - //! and desired time of a particular temporal feature in an - //! analyzed sound. - //! - //! \param i is an initial, or source, time point - //! \param t is a target time point - //! - //! The time points will be sorted before they are used. - //! If, in the sequences of initial and target time points, there are - //! exactly the same number of initial time points preceding i as - //! target time points preceding t, then time i will be warped to - //! time t in the dilation process. - void insert( double i, double t ); - -// -- dilation -- - - //! Replace the Partial envelope with a new envelope having the - //! same Breakpoints at times computed to align temporal features - //! in the sorted sequence of initial time points with their - //! counterparts the sorted sequence of target time points. - //! - //! Depending on the specification of initial and target time - //! points, the dilated Partial may have Breakpoints at times - //! less than 0, even if the original Partial did not. - //! - //! It is possible to have duplicate time points in either sequence. - //! Duplicate initial time points result in very localized stretching. - //! Duplicate target time points result in very localized compression. - //! - //! If all initial time points are greater than 0, then an implicit - //! time point at 0 is assumed in both initial and target sequences, - //! so the onset of a sound can be stretched without explcitly specifying a - //! zero point in each vector. (This seems most intuitive, and only looks - //! like an inconsistency if clients are using negative time points in - //! their Dilator, or Partials having Breakpoints before time 0, both - //! of which are probably unusual circumstances.) - //! - //! \param p is the Partial to dilate. - void dilate( Partial & p ) const; - - //! Function call operator: same as dilate( Partial & p ). - void operator() ( Partial & p ) const; - - //! Compute a new time for the specified Marker using - //! warpTime(), exactly as Partial Breakpoint times are - //! recomputed. This can be used to dilate the Markers - //! corresponding to a collection of Partials. - //! - //! \param m is the Marker whose time should be recomputed. - void dilate( Marker & m ) const; - - //! Function call operator: same as dilate( Marker & p ). - void operator() ( Marker & m ) const; - - //! Non-uniformly expand and contract the parameter envelopes of the each - //! Partial in the specified half-open range according to this Dilator's - //! stored initial and target (desired) times. - //! - //! \param dilate_begin is the beginning of a sequence of Partials to dilate. - //! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. Otherwise, this member - //! also works for sequences of Markers. - //! - //! \sa Dilator::dilate( Partial & p ) const - //! \sa Dilator::dilate( Marker & m ) const -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void dilate( Iter dilate_begin, Iter dilate_end ) const; -#else - inline - void dilate( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end ) const; -#endif - - //! Function call operator: same as - //! dilate( Iter dilate_begin, Iter dilate_end ) - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. Otherwise, this member - //! also works for sequences of Markers. - //! - //! \sa Dilator::dilate( Partial & p ) const - //! \sa Dilator::dilate( Marker & m ) const -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void operator() ( Iter dilate_begin, Iter dilate_end ) const; -#else - inline - void operator() ( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end ) const; -#endif - - //! Return the dilated time value corresponding to the specified initial time. - //! - //! \param currentTime is a pre-dilated time. - //! \return the dilated time corresponding to the initial time currentTime - double warpTime( double currentTime ) const; - -// -- static members -- - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Dilator using the specified initial and - //! target times, and apply it to a sequence of Partials. - //! - //! \param dilate_begin is the beginning of a sequence of Partials to dilate. - //! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. - //! \param ibegin is the beginning of a sequence of initial, or source, - //! time points. - //! \param iend is (one-past) the end of a sequence of initial, or - //! source, time points. - //! \param tbegin is the beginning of a sequence of target time points; - //! this sequence must be as long as the sequence of initial time - //! point described by ibegin and iend. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. Otherwise, this member - //! also works for sequences of Markers. - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only const double * arguments for the times, otherwise, any iterator - //! will do.. - //! - //! \sa Dilator::dilate( Partial & p ) const - //! \sa Dilator::dilate( Marker & m ) const -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename PartialsIter, typename TimeIter1, typename TimeIter2 > - static - void dilate( PartialsIter dilate_begin, PartialsIter dilate_end, - TimeIter1 ibegin, TimeIter1 iend, TimeIter2 tbegin ); -#else - static inline - void dilate( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end, - const double * ibegin, const double * iend, - const double * tbegin ); -#endif - -}; // end of class Dilator - - -// --------------------------------------------------------------------------- -// constructor (sequences of time points) -// --------------------------------------------------------------------------- -//! Construct a new Dilator using a range of initial time points -//! and a range of target (desired) time points. The client must -//! ensure that the target range has at least as many elements as -//! the initial range. -//! -//! \param ibegin is the beginning of a sequence of initial, or source, -//! time points. -//! \param iend is (one-past) the end of a sequence of initial, or -//! source, time points. -//! \param tbegin is the beginning of a sequence of target time points; -//! this sequence must be as long as the sequence of initial time -//! point described by ibegin and iend. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only const double * arguments. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -Dilator::Dilator( Iter1 ibegin, Iter1 iend, Iter2 tbegin ) -#else -inline -Dilator::Dilator( const double * ibegin, const double * iend, const double * tbegin ) -#endif -{ - while ( ibegin != iend ) - { - insert( *ibegin++, *tbegin++ ); - } -} - -// --------------------------------------------------------------------------- -// dilate (sequence of Partials or Markers) -// --------------------------------------------------------------------------- -//! Non-uniformly expand and contract the parameter envelopes of the each -//! Partial in the specified half-open range according to this Dilator's -//! stored initial and target (desired) times. -//! -//! \param dilate_begin is the beginning of a sequence of Partials to dilate. -//! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. Otherwise, this member -//! also works for sequences of Markers. -//! -//! \sa Dilator::dilate( Partial & p ) const -//! \sa Dilator::dilate( Marker & m ) const -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Dilator::dilate( Iter dilate_begin, Iter dilate_end ) const -#else -inline -void Dilator::dilate( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end ) const -#endif -{ - while ( dilate_begin != dilate_end ) - { - dilate( *(dilate_begin++) ); - } -} - -// --------------------------------------------------------------------------- -// Function call operator (sequence of Partials or Markers) -// --------------------------------------------------------------------------- -//! Function call operator: same as -//! dilate( Iter dilate_begin, Iter dilate_end ) -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. Otherwise, this member -//! also works for sequences of Markers. -//! -//! \sa Dilator::dilate( Partial & p ) const -//! \sa Dilator::dilate( Marker & m ) const -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Dilator::operator() ( Iter dilate_begin, Iter dilate_end ) const -#else -inline -void Dilator::operator() ( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end ) const -#endif -{ - dilate( dilate_begin, dilate_end ); -} - -// --------------------------------------------------------------------------- -// Function call operator (single Partial) -// --------------------------------------------------------------------------- -//! Function call operator: same as dilate( Partial & p ). -//! -//! \sa Dilator::dilate( Partial & p ) const -// -inline -void Dilator::operator() ( Partial & p ) const -{ - dilate( p ); -} - -// --------------------------------------------------------------------------- -// Function call operator (single Marker) -// --------------------------------------------------------------------------- -//! Function call operator: same as dilate( Marker & m ). -//! -//! \sa Dilator::dilate( Marker & m ) const -// -inline -void Dilator::operator() ( Marker & m ) const -{ - dilate( m ); -} - -// --------------------------------------------------------------------------- -// dilate (static) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! Construct a Dilator using the specified initial and -//! target times, and apply it to a sequence of Partials. -//! -//! \param dilate_begin is the beginning of a sequence of Partials to dilate. -//! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. -//! \param ibegin is the beginning of a sequence of initial, or source, -//! time points. -//! \param iend is (one-past) the end of a sequence of initial, or -//! source, time points. -//! \param tbegin is the beginning of a sequence of target time points; -//! this sequence must be as long as the sequence of initial time -//! point described by ibegin and iend. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. Otherwise, this member -//! also works for sequences of Markers. -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only const double * arguments for the times, otherwise, any iterator -//! will do.. -//! -//! \sa Dilator::dilate( Partial & p ) const -//! \sa Dilator::dilate( Marker & m ) const -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename PartialsIter, typename TimeIter1, typename TimeIter2 > -void Dilator::dilate( PartialsIter dilate_begin, PartialsIter dilate_end, - TimeIter1 ibegin, TimeIter1 iend, TimeIter2 tbegin ) -#else -inline -void Dilator::dilate( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end, - const double * ibegin, const double * iend, - const double * tbegin ) -#endif -{ - Dilator instance( ibegin, iend, tbegin ); - instance.dilate( dilate_begin, dilate_end ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_DILATOR_H */ diff --git a/loris_library/Source/include/loris/Distiller.h b/loris_library/Source/include/loris/Distiller.h deleted file mode 100644 index f1672ce..0000000 --- a/loris_library/Source/include/loris/Distiller.h +++ /dev/null @@ -1,370 +0,0 @@ -#ifndef INCLUDE_DISTILLER_H -#define INCLUDE_DISTILLER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Distiller.h - * - * Definition of class Distiller. - * - * Kelly Fitz, 20 Oct 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" - -#include "Notifier.h" // for debugging only - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Distiller -// -//! Class Distiller represents an algorithm for "distilling" a group of -//! Partials that logically represent a single component into a single -//! Partial. -//! -//! The sound morphing algorithm in Loris requires that Partials in a -//! given source be labeled uniquely, that is, no two Partials can have -//! the same label. The Distiller enforces this condition. All Partials -//! identified with a particular frequency channel (see Channelizer), and, -//! therefore, having a common label, are distilled into a single Partial, -//! leaving at most a single Partial per frequency channel and label. -//! Channels that contain no Partials are not represented in the distilled -//! data. Partials that are not labeled, that is, Partials having label 0, -//! are are left unmodified at the end of the Partial sequence. -//! -//! Distillation modifies the Partial container (a PartialList). All -//! Partials in the distilled range having a common label are replaced by -//! a single Partial in the distillation process. Only labeled -//! Partials are affected by distillation. -// -class Distiller -{ -// -- instance variables -- - - double _fadeTime, _gapTime; // distillation parameters - -// -- public interface -- -public: - -// -- global defaults and constants -- - - enum - { - - //! Default time in milliseconds over which Partials joined by - //! distillation fade to and from zero amplitude. Divide by - //! 1000 to use as a member function parameter. This parameter - //! should be the same in Distiller, Sieve, and Collator. - DefaultFadeTimeMs = 5, - - //! Default minimum duration in milliseconds of the silent - //! (zero-amplitude) gap between two Partials joined by - //! distillation. Divide by 1000 to use as a member function - //! parameter. This parameter should be the same in Distiller, - //! Sieve, and Collator. - DefaultSilentTimeMs = 1 - }; - -// -- construction -- - - //! Construct a new Distiller using the specified fade time - //! for gaps between Partials. When two non-overlapping Partials - //! are distilled into a single Partial, the distilled Partial - //! fades out at the end of the earlier Partial and back in again - //! at the onset of the later one. The fade time is the time over - //! which these fades occur. By default, use a 1 ms fade time. - //! The gap time is the additional time over which a Partial faded - //! out must remain at zero amplitude before it can fade back in. - //! By default, use a gap time of one tenth of a millisecond, to - //! prevent a pair of arbitrarily close null Breakpoints being - //! inserted. - //! - //! \param partialFadeTime is the time (in seconds) over - //! which Partials joined by distillation fade to - //! and from zero amplitude. (Default is - //! Distiller::DefaultFadeTime). - //! \param partialSilentTime is the minimum duration (in seconds) - //! of the silent (zero-amplitude) gap between two - //! Partials joined by distillation. (Default is - //! Distiller::DefaultSilentTime). - explicit - Distiller( double partialFadeTime = Distiller::DefaultFadeTimeMs/1000.0, - double partialSilentTime = Distiller::DefaultSilentTimeMs/1000.0 ); - - // Use compiler-generated copy, assign, and destroy. - -// -- distillation -- - - //! Distill labeled Partials in a collection leaving only a single - //! Partial per non-zero label. - //! - //! Unlabeled (zero-labeled) Partials are left unmodified at - //! the end of the distilled Partials. - //! - //! Return an iterator refering to the position of the first unlabeled Partial, - //! or the end of the distilled collection if there are no unlabeled Partials. - //! Since distillation is in-place, the Partials collection may be smaller - //! (fewer Partials) after distillation, and any iterators on the collection - //! may be invalidated. - //! - //! \post All labeled Partials in the collection are uniquely-labeled, - //! and all unlabeled Partials have been moved to the end of the - //! sequence. - //! \param partials is the collection of Partials to distill in-place - //! \return the position of the end of the range of distilled Partials, - //! which is either the end of the collection, or the position - //! or the first unlabeled Partial. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials - //! must be a PartialList, otherwise it can be any container type - //! storing Partials that supports at least bidirectional iterators. - //! - //! \sa Distiller::distill( Container & partials ) -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - typename Container::iterator distill( Container & partials ); -#else - inline - PartialList::iterator distill( PartialList & partials ); -#endif - - //! Function call operator: same as distill( PartialList & partials ). -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - typename Container::iterator operator() ( Container & partials ); -#else - PartialList::iterator operator() ( PartialList & partials ); -#endif - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! - //! \post All labeled Partials in the collection are uniquely-labeled, - //! and all unlabeled Partials have been moved to the end of the - //! sequence. - //! \param partials is the collection of Partials to distill in-place - //! \param partialFadeTime is the time (in seconds) over - //! which Partials joined by distillation fade to - //! and from zero amplitude. - //! \param partialSilentTime is the minimum duration (in seconds) - //! of the silent (zero-amplitude) gap between two - //! Partials joined by distillation. (Default is - //! Distiller::DefaultSilentTime). - //! \return the position of the end of the range of distilled Partials, - //! which is either the end of the collection, or the position - //! or the first unlabeled Partial. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials - //! must be a PartialList, otherwise it can be any container type - //! storing Partials that supports at least bidirectional iterators. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - static typename Container::iterator - distill( Container & partials, double partialFadeTime, - double partialSilentTime = DefaultSilentTimeMs/1000.0 ); -#else - static inline PartialList::iterator - distill( PartialList & partials, double partialFadeTime, - double partialSilentTime = DefaultSilentTimeMs/1000.0 ); -#endif - -private: - -// -- helpers -- - - //! Distill labeled Partials in a PartialList leaving only a single - //! Partial per non-zero label. - //! - //! Unlabeled (zero-labeled) Partials are left unmodified at - //! the end of the distilled Partials. - //! - //! Return an iterator refering to the position of the first unlabeled Partial, - //! or the end of the distilled collection if there are no unlabeled Partials. - //! Since distillation is in-place, the Partials collection may be smaller - //! (fewer Partials) after distillation, and any iterators on the collection - //! may be invalidated. - //! - //! \post All labeled Partials in the collection are uniquely-labeled, - //! and all unlabeled Partials have been moved to the end of the - //! sequence. - //! \param partials is the collection of Partials to distill in-place - //! \return the position of the end of the range of distilled Partials, - //! which is either the end of the collection, or the position - //! or the first unlabeled Partial. - PartialList::iterator distill_list( PartialList & partials ); - - //! Distill a list of Partials having a common label - //! into a single Partial with that label, and append it - //! to the distilled collection. If an empty list of Partials - //! is passed, then an empty Partial having the specified - //! label is appended. - void distillOne( PartialList & partials, Partial::label_type label, - PartialList & distilled ); - -}; // end of class Distiller - -// --------------------------------------------------------------------------- -// distill -// --------------------------------------------------------------------------- -//! Distill labeled Partials in a collection leaving only a single -//! Partial per non-zero label. -//! -//! Unlabeled (zero-labeled) Partials are left unmodified at -//! the end of the distilled Partials. -//! -//! Return an iterator refering to the position of the first unlabeled Partial, -//! or the end of the distilled collection if there are no unlabeled Partials. -//! Since distillation is in-place, the Partials collection may be smaller -//! (fewer Partials) after distillation, and any iterators on the collection -//! may be invalidated. -//! -//! \post All labeled Partials in the collection are uniquely-labeled, -//! and all unlabeled Partials have been moved to the end of the -//! sequence. -//! \param partials is the collection of Partials to distill in-place -//! \return the position of the end of the range of distilled Partials, -//! which is either the end of the collection, or the position -//! or the first unlabeled Partial. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then partials -//! must be a PartialList, otherwise it can be any container type -//! storing Partials that supports at least bidirectional iterators. -//! -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator Distiller::distill( Container & partials ) -{ - // This can be done so much more easily and - // efficiently on a list than on other containers - // that it is worth copying the Partials to a - // list for distillation, and then transfering - // them back. - // - // See below for a specialization for the case - // of the Container being a list, so no copy - // is needed. - PartialList pl( partials.begin(), partials.end() ); - PartialList::iterator it = distill_list( pl ); - - // pl has distilled Partials at beginning, and - // unlabeled Partials at end: - typename Container::iterator beginUnlabeled = - std::copy( pl.begin(), it, partials.begin() ); - - typename Container::iterator endUnlabeled = - std::copy( it, pl.end(), beginUnlabeled ); - - - partials.erase( endUnlabeled, partials.end() ); - - return beginUnlabeled; -} - -// specialization for PartialList container -template< > -inline -PartialList::iterator Distiller::distill( PartialList & partials ) -{ - debugger << "using PartialList version of distill to avoid copying" << endl; - return distill_list( partials ); -} -#else -inline -PartialList::iterator Distiller::distill( PartialList & partials ) -{ - return distill_list( partials ); -} -#endif - -// --------------------------------------------------------------------------- -// Function call operator -// --------------------------------------------------------------------------- -//! Function call operator: same as distill( PartialList & partials ). -//! -//! \sa Distiller::distill( Container & partials ) -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator Distiller::operator()( Container & partials ) -#else -inline -PartialList::iterator Distiller::operator()( PartialList & partials ) -#endif -{ - return distill( partials ); -} - -// --------------------------------------------------------------------------- -// distill -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! -//! \post All labeled Partials in the collection are uniquely-labeled, -//! and all unlabeled Partials have been moved to the end of the -//! sequence. -//! \param partials is the collection of Partials to distill in-place -//! \param partialFadeTime is the time (in seconds) over -//! which Partials joined by distillation fade to -//! and from zero amplitude. -//! \param partialSilentTime is the minimum duration (in seconds) -//! of the silent (zero-amplitude) gap between two -//! Partials joined by distillation. (Default is -//! Distiller::DefaultSilentTime). -//! \return the position of the end of the range of distilled Partials, -//! which is either the end of the collection, or the position -//! or the first unlabeled Partial. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then partials -//! must be a PartialList, otherwise it can be any container type -//! storing Partials that supports at least bidirectional iterators. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator -Distiller::distill( Container & partials, double partialFadeTime, - double partialSilentTime ) -#else -inline -PartialList::iterator -Distiller::distill( PartialList & partials, double partialFadeTime, - double partialSilentTime ) -#endif -{ - Distiller instance( partialFadeTime, partialSilentTime ); - return instance.distill( partials ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_DISTILLER_H */ diff --git a/loris_library/Source/include/loris/Envelope.h b/loris_library/Source/include/loris/Envelope.h deleted file mode 100644 index 832619a..0000000 --- a/loris_library/Source/include/loris/Envelope.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef INCLUDE_ENVELOPE_H -#define INCLUDE_ENVELOPE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Envelope.h - * - * Definition of abstract interface class Envelope. - * - * Kelly Fitz, 21 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include // for autoptr - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Envelope -// -//! Envelope is an base class for objects representing real functions -//! of time. -//! -//! Class Envelope is an abstract base class, specifying interface for -//! prototypable (clonable) objects representing generic, real-valued -//! (double) functions of one real-valued (double) time argument. Derived -//! classes (like BreakpointEnvelope) must implement valueAt() and -//! clone(), the latter to support the Prototype pattern. Clients of -//! Envelope, like Morpher and Distiller, can use prototype Envelopes to -//! make their own private Envelopes. -//! -//! \sa Distiller, Envelope, Morpher -// -class Envelope -{ -// -- public interface -- -public: -// -- construction -- - - // allow compiler to generate constructors - - //! Destroy this Envelope (virtual to allow subclassing). - virtual ~Envelope( void ); - -// -- Envelope interface -- - - //! Return an exact copy of this Envelope (following the Prototype - //! pattern). - virtual Envelope * clone( void ) const = 0; - - //! Return the value of this Envelope at the specified time. - virtual double valueAt( double x ) const = 0; - -}; // end of abstract class Envelope - - -// --------------------------------------------------------------------------- -// class ScaleAndOffsetEnvelope -// -//! ScaleAndOffsetEnvelope is an derived Envelope class for objects -//! representing envelopes having a scale and offset applied (in that order). - -class ScaleAndOffsetEnvelope : public Envelope -{ -// -- public interface -- -public: -// -- construction -- - - //! Construct a new envelope that is a scaled and offset - //! version of another. - ScaleAndOffsetEnvelope( const Envelope & e, double scale, double offset ) : - m_env( e.clone() ), - m_scale( scale ), - m_offset( offset ) - { - } - - //! Construct a copy of an envelope. - ScaleAndOffsetEnvelope( const ScaleAndOffsetEnvelope & rhs ) : - m_env( rhs.m_env->clone() ), - m_scale( rhs.m_scale ), - m_offset( rhs.m_offset ) - { - } - - //! Assignment from another envelope. - ScaleAndOffsetEnvelope & - operator=( const ScaleAndOffsetEnvelope & rhs ) - { - if ( &rhs != this ) - { - m_env.reset( rhs.m_env->clone() ); - m_scale = rhs.m_scale; - m_offset = rhs.m_offset; - } - return *this; - } - -// -- Envelope interface -- - - //! Return an exact copy of this Envelope (following the Prototype - //! pattern). - ScaleAndOffsetEnvelope * clone( void ) const - { - return new ScaleAndOffsetEnvelope( *this ); - } - - //! Return the value of this Envelope at the specified time. - virtual double valueAt( double x ) const - { - return m_offset + ( m_scale * m_env->valueAt( x ) ); - } - -// -- private member variables -- - -private: - - std::auto_ptr< Envelope > m_env; - double m_scale, m_offset; - -}; // end of class ScaleAndOffsetEnvelope - - -// --------------------------------------------------------------------------- -// math operators -// --------------------------------------------------------------------------- - -inline -ScaleAndOffsetEnvelope -operator*( const Envelope & e, double x ) -{ - return ScaleAndOffsetEnvelope( e, x, 0 ); -} - -inline -ScaleAndOffsetEnvelope -operator*( double x, const Envelope & e ) -{ - return e * x; -} - - - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_ENVELOPE_H */ diff --git a/loris_library/Source/include/loris/Exception.h b/loris_library/Source/include/loris/Exception.h deleted file mode 100644 index e21355c..0000000 --- a/loris_library/Source/include/loris/Exception.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef INCLUDE_EXCEPTION_H_DEPRECATED -#define INCLUDE_EXCEPTION_H_DEPRECATED -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Exception.h - * - * This file formerly defined class Exception, a generic exception class, and - * commonly-used derived exception classes, but the name caused build problems - * on case-insensitive systems having a system header called exception.h, so - * the name has been changed to LorisExceptions.h. This file is included as - * legacy support. New code should use LorisExceptions.h. - * - * Kelly Fitz, 17 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "LorisExceptions.h" - -#endif /* ndef INCLUDE_EXCEPTION_H_DEPRECATED */ diff --git a/loris_library/Source/include/loris/F0Estimate.h b/loris_library/Source/include/loris/F0Estimate.h deleted file mode 100644 index a20e81e..0000000 --- a/loris_library/Source/include/loris/F0Estimate.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef INCLUDE_F0ESTIMATE_H -#define INCLUDE_F0ESTIMATE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * F0Estimate.h - * - * Implementation of an iterative alrogithm for computing an - * estimate of fundamental frequency from a sequence of sinusoidal - * frequencies and amplitudes using a likelihood estimator - * adapted from Quatieri's Speech Signal Processing text. The - * algorithm here takes advantage of the fact that spectral peaks - * have already been identified and extracted in the analysis/modeling - * process. - * - * Kelly Fitz, 28 March 2006 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class F0Estimate -// -//! Represents a configuration of an iterative alrogithm for computing an -//! estimate of fundamental frequency from a sequence of sinusoidal -//! frequencies and amplitudes using a likelihood estimator adapted -//! from Quatieri's Speech Signal Processing text. This algorithm takes -//! advantage of the fact that spectral peaks have already been identified -//! and extracted in the analysis/modeling process. -//! -//! The algorithm consists of the following steps: -//! 1) Identify candidate F0s as the integer divisors of the sinusoidal -//! frequencies provided, within the specified range (this algorithm -//! relies on the reasonable assumption that for any frequency recognized -//! as a likely F0, at least one of the sinusoidal frequencies must -//! represent a harmonic, the likelihood function makes this same -//! assumption) -//! 2) Select the highest frequency candidate (within range) that maximizes -//! the likelihood function (because all subharmonics of the true F0 will -//! be equal in likelihood to the true F0, but no higher frequency can -//! be as likely). -//! 2a) Check the likelihood of integer multiples of the best candidate, -//! choose the highest multiple (within the specified range) that -//! as likely as the best candidate frequency to be the new best -//! candidate. -//! 3) Refine the best candidate using the secant method for refining the -//! root of the derivative of the likelihood function in the neighborhood -//! of the best candidate (because a peak in the likelihood function is -//! a root of the derivative of that function). -// - -class F0Estimate -{ -private: - - double m_frequency; //! estimated fundamental frequency in Hz - double m_confidence; //! normalized confidence for this estimate, - //! equal to 1.0 when all frequencies are perfect - //! harmonics of this estimate's frequency - -public: - - // --- lifecycle --- - - //! Construct from parameters of the iterative F0 estimation - //! algorithm. Find candidate F0 estimates as integer divisors - //! of the peak frequencies, pick the highest frequency of the - //! most likely candidates, and refine that estiamte using the - //! secant method. - //! - //! Store the frequency and the normalized value of the - //! likelihood function at that frequency (1.0 indicates that - //! all the peaks are perfect harmonics of the estimated - //! frequency). - - F0Estimate( const std::vector & amps, - const std::vector & freqs, - double fmin, double fmax, - double resolution ); - - // default copy/assign/destroy are OK - - - // Not sure whether or why these would be useful. - // - // F0Estimate( void ) : m_frequency( 0 ), m_confidence( 0 ) {} - // F0Estimate( double f, double c ) : m_frequency( f ), m_confidence( c ) {} - - - // --- accessors --- - - //! Return the F0 frequency estimate, in Hz, for this estimate. - - double frequency( void ) const { return m_frequency; } - - //! Return the normalized confidence for this estimate, - //! equal to 1.0 when all frequencies are perfect - //! harmonics of this estimate's frequency. - - double confidence( void ) const { return m_confidence; } - - - -}; // end of class F0Estimate - - -} // end of namespace Loris - -#endif // ndef INCLUDE_F0ESTIMATE_H diff --git a/loris_library/Source/include/loris/Filter.h b/loris_library/Source/include/loris/Filter.h deleted file mode 100644 index c4ddfc6..0000000 --- a/loris_library/Source/include/loris/Filter.h +++ /dev/null @@ -1,250 +0,0 @@ -#ifndef INCLUDE_FILTER_H -#define INCLUDE_FILTER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Filter.h - * - * Definition of class Loris::Filter, a generic digital filter of - * arbitrary order having both feed-forward and feedback coefficients. - * - * Kelly Fitz, 1 Sept 1999 - * revised 9 Oct 2009 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "LorisExceptions.h" -#include "Notifier.h" - -#include -#include -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Filter -// -//! Filter is an Direct Form II realization of a filter specified -//! by its difference equation coefficients and (optionally) gain, -//! applied to the filter output (defaults to 1.). Coefficients are -//! specified and stored in order of increasing delay. -//! -//! Implements the rational transfer function -//! -//! -1 -nb -//! b[0] + b[1]z + ... + b[nb] z -//! Y(z) = G ---------------------------------- X(z) -//! -1 -na -//! a[0] + a[1]z + ... + a[na] z -//! -//! where b[k] are the feed forward coefficients, and a[k] are the feedback -//! coefficients. If a[0] is not 1, then both a and b are normalized by a[0]. -//! G is the additional filter gain, and is unity if unspecified. -//! -//! -//! Filter is implemented using a std::deque to store the filter state, -//! and relies on the efficiency of that class. If deque is not implemented -//! using some sort of circular buffer (as it should be -- deque is guaranteed -//! to be efficient for repeated insertion and removal at both ends), then -//! this filter class will be slow. -// -class Filter -{ -public: - -// --- lifecycle --- - - // default construction - //! Construct a filter with an all-pass unity gain response. - Filter( void ); - - // initialized construction - //! Initialize a Filter having the specified coefficients, and - //! order equal to the larger of the two coefficient ranges. - //! Coefficients in the sequences are stored in increasing order - //! (lowest order coefficient first). - //! - //! If template members are allowed, then the coefficients - //! can be stored in any kind of iterator range, otherwise, - //! they must be in an array of doubles. - //! - //! \param ffwdbegin is the beginning of a sequence of feed-forward coefficients - //! \param ffwdend is the end of a sequence of feed-forward coefficients - //! \param fbackbegin is the beginning of a sequence of feedback coefficients - //! \param fbackend is the end of a sequence of feedback coefficients - //! \param gain is an optional gain scale applied to the filtered signal - // -#if !defined(NO_TEMPLATE_MEMBERS) - template - Filter( IterT1 ffwdbegin, IterT1 ffwdend, // feed-forward coeffs - IterT2 fbackbegin, IterT2 fbackend, // feedback coeffs - double gain = 1. ); -#else - Filter( const double * ffwdbegin, const double * ffwdend, // feed-forward coeffs - const double * fbackbegin, const double * fbackend, // feedback coeffs - double gain = 1. ); -#endif - - - // copy constructor - //! Make a copy of another digital filter. - //! Do not copy the filter state (delay line). - Filter( const Filter & other ); - - // assignment operator - //! Make a copy of another digital filter. - //! Do not copy the filter state (delay line). - Filter & operator=( const Filter & rhs ); - - //! Destructor is virtual to enable subclassing. Subclasses may specialize - //! construction, and may add functionality, but for efficiency, the filtering - //! operation is non-virtual. - ~Filter( void ); - - -// --- filtering --- - - //! Compute a filtered sample from the next input sample. - //! - //! \param input is the next input sample - //! \return the next output sample - double apply( double input ); - - //! Function call operator, same as sample(). - //! - //! \sa apply - double operator() ( double input ) { return apply(input); } - -// --- access/mutation --- - - //! Provide access to the numerator (feed-forward) coefficients - //! of this filter. The coefficients are stored in order of increasing - //! delay (lowest order coefficient first). - - std::vector< double > numerator( void ); - - //! Provide access to the numerator (feed-forward) coefficients - //! of this filter. The coefficients are stored in order of increasing - //! delay (lowest order coefficient first). - - const std::vector< double > numerator( void ) const; - - //! Provide access to the denominator (feedback) coefficients - //! of this filter. The coefficients are stored in order of increasing - //! delay (lowest order coefficient first). - - std::vector< double > denominator( void ); - - //! Provide access to the denominator (feedback) coefficients - //! of this filter. The coefficients are stored in order of increasing - //! delay (lowest order coefficient first). - - const std::vector< double > denominator( void ) const; - - - //! Clear the filter state. - void clear( void ); - - -private: - -// --- implementation --- - - //! single delay line for Direct-Form II implementation - std::deque< double > m_delayline; - - //! feed-forward coefficients - std::vector< double > m_ffwdcoefs; - - //! feedback coefficients - std::vector< double > m_fbackcoefs; - - //! filter gain (applied to output) - double m_gain; - -}; // end of class Filter - - - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Initialize a Filter having the specified coefficients, and -//! order equal to the larger of the two coefficient ranges. -//! Coefficients in the sequences are stored in increasing order -//! (lowest order coefficient first). -//! -//! If template members are allowed, then the coefficients -//! can be stored in any kind of iterator range, otherwise, -//! they must be in an array of doubles. -//! -//! \param ffwdbegin is the beginning of a sequence of feed-forward coefficients -//! \param ffwdend is the end of a sequence of feed-forward coefficients -//! \param fbackbegin is the beginning of a sequence of feedback coefficients -//! \param fbackend is the end of a sequence of feedback coefficients -//! \param gain is an optional gain scale applied to the filtered signal -// -#if !defined(NO_TEMPLATE_MEMBERS) -template -Filter::Filter( IterT1 ffwdbegin, IterT1 ffwdend, // feed-forward coeffs - IterT2 fbackbegin, IterT2 fbackend, // feedback coeffs - double gain ) : -#else -inline -Filter::Filter( const double * ffwdbegin, const double * ffwdend, // feed-forward coeffs - const double * fbackbegin, const double * fbackend, // feedback coeffs - double gain ) : -#endif - m_ffwdcoefs( ffwdbegin, ffwdend ), - m_fbackcoefs( fbackbegin, fbackend ), - m_delayline( std::max( ffwdend-ffwdbegin, fbackend-fbackbegin ) - 1, 0. ), - m_gain( gain ) -{ - if ( *fbackbegin == 0. ) - { - Throw( InvalidObject, - "Tried to create a Filter with feeback coefficient at zero delay equal to 0.0" ); - } - - // normalize the coefficients by 1/a[0], if a[0] is not equal to 1.0 - // (already checked for a[0] == 0 above) - if ( *fbackbegin != 1. ) - { - // scale all filter coefficients by a[0]: - std::transform( m_ffwdcoefs.begin(), m_ffwdcoefs.end(), m_ffwdcoefs.begin(), - std::bind2nd( std::divides(), *fbackbegin ) ); - std::transform( m_fbackcoefs.begin(), m_fbackcoefs.end(), m_fbackcoefs.begin(), - std::bind2nd( std::divides(), *fbackbegin ) ); - m_fbackcoefs[0] = 1.; - } -} - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_FILTER_H */ diff --git a/loris_library/Source/include/loris/FourierTransform.h b/loris_library/Source/include/loris/FourierTransform.h deleted file mode 100644 index 34867ee..0000000 --- a/loris_library/Source/include/loris/FourierTransform.h +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef INCLUDE_FOURIERTRANSFORM_H -#define INCLUDE_FOURIERTRANSFORM_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * FourierTransform.h - * - * Definition of class Loris::FourierTransform, providing a simplified - * uniform interface to the FFTW library (www.fftw.org), version 2.1.3 - * or newer (including version 3), or to the General Purpose FFT package - * by Takuya OOURA, http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html if - * FFTW is unavailable. - * - * Kelly Fitz, 2 Jun 2006 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include -#include - -// begin namespace -namespace Loris { - -// insulating implementation class, defined in FourierTransform.C -class FTimpl; - -// --------------------------------------------------------------------------- -// class FourierTransform -// -//! FourierTransform provides a simplified interface to the FFTW library -//! (www.fftw.org). Loris uses the FFTW library to perform efficient -//! Fourier transforms of arbitrary length. Clients store and access -//! the in-place transform data as a sequence of std::complex< double >. -//! Samples are stored in the FourierTransform instance using subscript -//! or iterator access, the transform is computed by the transform member, -//! and the transformed samples replace the input samples, and are -//! accessed by subscript or iterator. FourierTransform computes a complex -//! transform, so it can be used to invert a transform of real samples -//! as well. Uses the standard library complex class, which implements -//! arithmetic operations. -//! -//! Supports FFTW versions 2 and 3. -//! Does not make use of FFTW "wisdom" to speed up transform computation. -//! -//! If FFTW is unavailable, uses instead the General Purpose FFT package -//! by Takuya OOURA, http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html defined -//! in fftsg.c for power-of-two transforms, and a very slow direct DFT -//! implementation for non-PO2 transforms. -// -class FourierTransform -{ -// -- public interface -- -public: - - //! An unsigned integral type large enough - //! to represent the length of any transform. - typedef std::vector< std::complex< double > >::size_type size_type; - - //! The type of a non-const iterator of (complex) transform samples. - typedef std::vector< std::complex< double > >::iterator iterator; - - //! The type of a const iterator of (complex) transform samples. - typedef std::vector< std::complex< double > >::const_iterator const_iterator; - -// --- lifecycle --- - - //! Initialize a new FourierTransform of the specified size. - //! - //! \param len is the length of the transform in samples (the - //! number of samples in the transform) - //! \throw RuntimeError if the necessary buffers cannot be - //! allocated, or there is an error configuring FFTW. - FourierTransform( size_type len ); - - //! Initialize a new FourierTransform that is a copy of another, - //! having the same size and the same buffer contents. - //! - //! \param rhs is the instance to copy - //! \throw RuntimeError if the necessary buffers cannot be - //! allocated, or there is an error configuring FFTW. - FourierTransform( const FourierTransform & rhs ); - - //! Free the resources associated with this FourierTransform. - ~FourierTransform( void ); - -// --- operators --- - - //! Make this FourierTransform a copy of another, having - //! the same size and buffer contents. - //! - //! \param rhs is the instance to copy - //! \return a refernce to this instance - //! \throw RuntimeError if the necessary buffers cannot be - //! allocated, or there is an error configuring FFTW. - FourierTransform & operator= ( const FourierTransform & rhs ); - - -// --- access/mutation --- - - //! Access (read/write) a transform sample by index. - //! Use this member to fill the transform buffer before - //! computing the transform, and to access the samples - //! after computing the transform. (inlined for speed) - //! - //! \param index is the index or rank of the complex - //! transform sample to access. Zero is the first - //! position in the buffer. - //! \return non-const reference to the std::complex< double > - //! at the specified position in the buffer. - std::complex< double > & operator[] ( size_type index ) - { - return _buffer[ index ]; - } - - //! Access (read-only) a transform sample by index. - //! Use this member to fill the transform buffer before - //! computing the transform, and to access the samples - //! after computing the transform. (inlined for speed) - //! - //! \param index is the index or rank of the complex - //! transform sample to access. Zero is the first - //! position in the buffer. - //! \return const reference to the std::complex< double > - //! at the specified position in the buffer. - const std::complex< double > & operator[] ( size_type index ) const - { - return _buffer[ index ]; - } - - //! Return an iterator refering to the beginning of the sequence of - //! complex samples in the transform buffer. - //! - //! \return a non-const iterator refering to the first position - //! in the transform buffer. - iterator begin( void ) - { - return _buffer.begin(); - } - - //! Return an iterator refering to the end of the sequence of - //! complex samples in the transform buffer. - //! - //! \return a non-const iterator refering to one past the last - //! position in the transform buffer. - iterator end( void ) - { - return _buffer.end(); - } - - //! Return a const iterator refering to the beginning of the sequence of - //! complex samples in the transform buffer. - //! - //! \return a const iterator refering to the first position - //! in the transform buffer. - const_iterator begin( void ) const - { - return _buffer.begin(); - } - - //! Return a const iterator refering to the end of the sequence of - //! complex samples in the transform buffer. - //! - //! \return a const iterator refering to one past the last - //! position in the transform buffer. - const_iterator end( void ) const - { - return _buffer.end(); - } - -// --- operations --- - - //! Compute the Fourier transform of the samples stored in the - //! transform buffer. The samples stored in the transform buffer - //! (accessed by index or by iterator) are replaced by the - //! transformed samples, in-place. - void transform( void ); - -// --- inquiry --- - - //! Return the length of the transform (in samples). - //! - //! \return the length of the transform in samples. - size_type size( void ) const ; - -// -- instance variables -- -private: - - //! buffer containing the complex transform input before - //! computing the transform, and the complex transform output - //! after computing the transform - std::vector< std::complex< double > > _buffer; - - // insulating implementation instance (defined in - // FourierTransform.C), conceals interface to FFTW - FTimpl * _impl; - -}; // end of class FourierTransform - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_FOURIERTRANSFORM_H */ diff --git a/loris_library/Source/include/loris/FrequencyReference.h b/loris_library/Source/include/loris/FrequencyReference.h deleted file mode 100644 index 366c57f..0000000 --- a/loris_library/Source/include/loris/FrequencyReference.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef INCLUDE_FREQUENCYREFERENCE_H -#define INCLUDE_FREQUENCYREFERENCE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * FrequencyReference.h - * - * Definition of class FrequencyReference. - * - * Kelly Fitz, 3 Dec 2001 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Envelope.h" -#include "PartialList.h" -#include - -// begin namespace -namespace Loris { - -class LinearEnvelope; - -// --------------------------------------------------------------------------- -// class FrequencyReference -// -//! Class FrequencyReference represents a reference frequency envelope -//! derived from an estimate of the fundamental frequency of a given range -//! of Partials within in a specified frequency range. This reference envelope -//! can be used for channelizing the Partials in preparation for morphing -//! (see Channelizer.h). -//! -//! FrequencyReference implements the Envelope interface (see -//! Envelope.h). -// -class FrequencyReference : public Envelope -{ -// -- instance variables -- - std::auto_ptr< LinearEnvelope > _env; - -// -- public interface -- -public: -// -- construction -- - - //! Construct a new fundamental FrequencyReference derived from the - //! specified half-open (STL-style) range of Partials that lies - //! within the speficied average frequency range. Construct the - //! reference envelope with approximately numSamps points. - //! - //! \param begin The beginning of a range of Partials from which to - //! construct a frequency refence envelope. - //! \param end The end of a range of Partials from which to - //! construct a frequency refence envelope. - //! \param minFreq The minimum expected fundamental frequency. - //! \param maxFreq The maximum expected fundamental frequency. - //! \param numSamps The approximate number of estimate of the - //! fundamental frequency from which to construct the - //! frequency reference envelope. - FrequencyReference( PartialList::const_iterator begin, - PartialList::const_iterator end, - double minFreq, double maxFreq, long numSamps ); - - //! Construct a new fundamental FrequencyReference derived from the - //! specified half-open (STL-style) range of Partials that lies - //! within the speficied average frequency range. Construct the - //! reference envelope from fundamental estimates taken every - //! five milliseconds. - //! - //! \param begin The beginning of a range of Partials from which to - //! construct a frequency refence envelope. - //! \param end The end of a range of Partials from which to - //! construct a frequency refence envelope. - //! \param minFreq The minimum expected fundamental frequency. - //! \param maxFreq The maximum expected fundamental frequency. - FrequencyReference( PartialList::const_iterator begin, - PartialList::const_iterator end, - double minFreq, double maxFreq ); - - - //! Construct a new FrequencyReference that is an exact copy of the - //! specified FrequencyReference. - FrequencyReference( const FrequencyReference & other ); - - //! Assignment operator: make this FrequencyReference an exact copy - //! of the specified FrequencyReference. - FrequencyReference & operator= ( const FrequencyReference & other ); - - //! Destroy this FrequencyReference. - ~FrequencyReference(); - -// -- conversion to LinearEnvelope -- - - //! Return a LinearEnvelope that evaluates indentically to this - //! FrequencyReference at all time. - LinearEnvelope envelope( void ) const; - -// -- Envelope interface -- - - //! Return an exact copy of this FrequencyReference (following the - //! Prototype pattern). - virtual FrequencyReference * clone( void ) const; - - //! Return the frequency value (in Hz) of this FrequencyReference at the - //! specified time. - virtual double valueAt( double x ) const; - -}; // end of class FrequencyReference - -} // end of namespace Loris - -#endif // ndef INCLUDE_FREQUENCYREFERENCE_H diff --git a/loris_library/Source/include/loris/Fundamental.h b/loris_library/Source/include/loris/Fundamental.h deleted file mode 100644 index 5971408..0000000 --- a/loris_library/Source/include/loris/Fundamental.h +++ /dev/null @@ -1,737 +0,0 @@ -#ifndef INCLUDE_FUNDAMENTAL_H -#define INCLUDE_FUNDAMENTAL_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Fundamental.h - * - * Definition of classes for computing an estimate of time-varying - * fundamental frequency from either a sequence of samples or a - * collection of Partials using a frequency domain maximum likelihood - * algorithm adapted from Quatieri's speech signal processing textbook. - * - * Kelly Fitz, 25 March 2008 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "LinearEnvelope.h" -#include "PartialList.h" -#include "F0Estimate.h" - -#include -#include - -// begin namespace -namespace Loris { - -class ReassignedSpectrum; - -// --------------------------------------------------------------------------- -// class FundamentalEstimator -// -//! Base class for fundamental estimation, common storage for member -//! variable parameters, type definitions, and constants. - -class FundamentalEstimator -{ -public: - -// -- types -- - - typedef F0Estimate value_type; - -// -- constants -- - - enum { - - DefaultAmpFloor = -60, //! the default absolute amplitude threshold in dB - - DefaultAmpRange = 30, //! the default floating amplitude threshold in dB - - DefaultFreqCeiling = 4000, //! the default frequency threshold in Hz - - DefaultPrecisionOver100 = 10, //! the default frequency precision in 1/100 Hz - - DefaultMinConfidencePct = 90 //! the default required percent confidence to - //! return an estimate (100 is absolute confidence) - }; - - -// -- lifecycle -- - -protected: - - //! Construct a new estimator with specified precision and - //! other parameters given default values. - //! - //! The specified precision is used to terminate the iterative - //! estimation procedure. - //! - //! \param precisionHz is the precision in Hz with which the - //! fundamental estimates will be made. - FundamentalEstimator( double precisionHz ); - -public: - - //! Destructor - virtual ~FundamentalEstimator( void ); - - - // compiler-generated copy and assignment are OK - - -// -- parameter access -- - - //! Return the absolute amplitude threshold in (negative) dB, - //! below which spectral peaks will not be considered in the - //! estimation of the fundamental (default is 30 dB). - double ampFloor( void ) const; - - //! Return the amplitude range in dB, - //! relative to strongest peak in a frame, floating - //! amplitude threshold (negative) below which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is 30 dB). - double ampRange( void ) const; - - //! Return the frequency ceiling in Hz, the - //! frequency threshold above which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is 10 kHz). - double freqCeiling( void ) const; - - //! Return the precision of the estimate in Hz, the - //! fundamental frequency will be estimated to - //! within this range (default is 0.1 Hz). - double precision( void ) const; - -// -- parameter mutation -- - - //! Set the absolute amplitude threshold in (negative) dB, - //! below which spectral peaks will not be considered in the - //! estimation of the fundamental (default is 30 dB). - //! - //! \param x is the new value of this parameter. - void setAmpFloor( double x ); - - //! Set the amplitude range in dB, - //! relative to strongest peak in a frame, floating - //! amplitude threshold (negative) below which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is 30 dB). - //! - //! \param x is the new value of this parameter. - void setAmpRange( double x ); - - //! Set the frequency ceiling in Hz, the - //! frequency threshold above which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is 10 kHz). Must be - //! greater than the lower bound. - //! - //! \param x is the new value of this parameter. - void setFreqCeiling( double x ); - - //! Set the precision of the estimate in Hz, the - //! fundamental frequency will be estimated to - //! within this range (default is 0.1 Hz). - //! - //! \param x is the new value of this parameter. - void setPrecision( double x ); - - -protected: - -// -- parameter member variables -- - - - double m_precision; //! in Hz, fundamental frequency will be estimated to - //! within this range (default is 0.1 Hz) - - double m_ampFloor; //! absolute amplitude threshold below which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is equivalent to 60 dB - //! quieter than a full scale sinusoid) - - double m_ampRange; //! floating amplitude threshold relative to the peak - //! having the largest magnitude below which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is equivalent to 30 dB) - - double m_freqCeiling; //! in Hz, frequency threshold above which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is 10 kHz) - - -}; // end of base class FundamentalEstimator - - - -// --------------------------------------------------------------------------- -// class FundamentalFromSamples -// -//! Class FundamentalFromSamples represents an algorithm for -//! time-varying fundamental frequency estimation based on -//! time-frequency reassigned spectral analysis of a sequence -//! of samples. This class is adapted from the Analyzer class -//! (see Analyzer.h), and performs the same spectral analysis -//! and peak extraction, but does not form Partials. -//! -//! For more information about Reassigned Bandwidth-Enhanced -//! Analysis and the Reassigned Bandwidth-Enhanced Additive Sound -//! Model, refer to the Loris website: www.cerlsoundgroup.org/Loris/. -// -class FundamentalFromSamples : public FundamentalEstimator -{ -// -- public interface -- - -public: - -// -- lifecycle -- - - //! Construct a new estimator configured with the given - //! analysis window width (main lobe, zero-to-zero). All other - //! spectrum analysis parameters are computed from the specified - //! window width. - //! - //! The specified precision is used to terminate the iterative - //! estimation procedure. If unspecified, the default value, - //! DefaultPrecisionOver100 * 100 is used. - //! - //! \param windowWidthHz is the main lobe width of the Kaiser - //! analysis window in Hz. - //! - //! \param precisionHz is the precision in Hz with which the - //! fundamental estimates will be made. - FundamentalFromSamples( double winWidthHz, - double precisionHz = DefaultPrecisionOver100 * 0.01 ); - - - - //! Destructor - ~FundamentalFromSamples( void ); - -// -- fundamental frequency estimation -- - - // buildEnvelope - // - //! Construct a linear envelope from fundamental frequency - //! estimates taken at the specified interval in seconds - //! starting at tbeg (seconds) and ending before tend (seconds). - //! - //! \param samps is the beginning of a sequence of samples - //! \param sampsEnd is the end of the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param tbeg is the beginning of the time interval (in seconds) - //! \param tend is the end of the time interval (in seconds) - //! \param interval is the time between breakpoints in the - //! fundamental frequency envelope (in seconds) - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param confidenceThreshold is the minimum confidence level - //! resuired for a fundamental frequency estimate to be - //! added to the envelope. Lower confidence estimates are - //! not added, the envelope returned will not contain - //! breakpoints at times associated with low confidence - //! estimates - //! \return a LinearEnvelope composed of breakpoints corresponding to - //! the fundamental frequency estimates at samples of the span - //! tbeg to tend at the specified sampling interval, only estimates - //! having confidence level exceeding the specified confidence - //! threshold are added to the envelope - LinearEnvelope buildEnvelope( const double * sampsBeg, - const double * sampsEnd, - double sampleRate, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ); - - // buildEnvelope - // - //! Construct a linear envelope from fundamental frequency - //! estimates taken at the specified interval in seconds - //! starting at tbeg (seconds) and ending before tend (seconds). - //! - //! \param samps is the beginning of a sequence of samples - //! \param nsamps is the length of the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param tbeg is the beginning of the time interval (in seconds) - //! \param tend is the end of the time interval (in seconds) - //! \param interval is the time between breakpoints in the - //! fundamental frequency envelope (in seconds) - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param confidenceThreshold is the minimum confidence level - //! resuired for a fundamental frequency estimate to be - //! added to the envelope. Lower confidence estimates are - //! not added, the envelope returned will not contain - //! breakpoints at times associated with low confidence - //! estimates - //! \return a LinearEnvelope composed of breakpoints corresponding to - //! the fundamental frequency estimates at samples of the span - //! tbeg to tend at the specified sampling interval, only estimates - //! having confidence level exceeding the specified confidence - //! threshold are added to the envelope - LinearEnvelope buildEnvelope( const double * sampsBeg, - unsigned long nsamps, - double sampleRate, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ) - { - return buildEnvelope( sampsBeg, sampsBeg + nsamps, sampleRate, - tbeg, tend, interval, - lowerFreqBound, upperFreqBound, - confidenceThreshold ); - } - - - // buildEnvelope - // - //! Construct a linear envelope from fundamental frequency - //! estimates taken at the specified interval in seconds - //! starting at tbeg (seconds) and ending before tend (seconds). - //! - //! \param samps is the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param tbeg is the beginning of the time interval (in seconds) - //! \param tend is the end of the time interval (in seconds) - //! \param interval is the time between breakpoints in the - //! fundamental frequency envelope (in seconds) - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param confidenceThreshold is the minimum confidence level - //! resuired for a fundamental frequency estimate to be - //! added to the envelope. Lower confidence estimates are - //! not added, the envelope returned will not contain - //! breakpoints at times associated with low confidence - //! estimates - //! \return a LinearEnvelope composed of breakpoints corresponding to - //! the fundamental frequency estimates at samples of the span - //! tbeg to tend at the specified sampling interval, only estimates - //! having confidence level exceeding the specified confidence - //! threshold are added to the envelope - LinearEnvelope buildEnvelope( const std::vector< double > & samps, - double sampleRate, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ) - { - return buildEnvelope( &samps[0], &samps[0] + samps.size(), sampleRate, - tbeg, tend, interval, - lowerFreqBound, upperFreqBound, - confidenceThreshold ); - } - - - // estimateAt - // - //! Return an estimate of the fundamental frequency computed - //! at the specified time. The F0Estimate returned stores the - //! estimate of the fundamental frequency (in Hz) and the - //! relative confidence (from 0 to 1) associated with that - //! estimate. - //! - //! \param sampsBeg is the beginning of a sequence of samples - //! \param sampsEnd is the end of the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param time is the time in seconds at which to attempt to estimate - //! the fundamental frequency - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \return the estimate of fundamental frequency in Hz and the - //! confidence associated with that estimate (see - //! F0Estimate.h) - - value_type estimateAt( const double * sampsBeg, - const double * sampsEnd, - double sampleRate, - double time, - double lowerFreqBound, double upperFreqBound ); - - // estimateAt - // - //! Return an estimate of the fundamental frequency computed - //! at the specified time. The F0Estimate returned stores the - //! estimate of the fundamental frequency (in Hz) and the - //! relative confidence (from 0 to 1) associated with that - //! estimate. - //! - //! \param samps is the beginning of a sequence of samples - //! \param nsamps is the length of the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param time is the time in seconds at which to attempt to estimate - //! the fundamental frequency - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \return the estimate of fundamental frequency in Hz and the - //! confidence associated with that estimate (see - //! F0Estimate.h) - - value_type estimateAt( const double * sampsBeg, - unsigned long nsamps, - double sampleRate, - double time, - double lowerFreqBound, double upperFreqBound ) - { - return estimateAt( sampsBeg, sampsBeg + nsamps, sampleRate, - time, lowerFreqBound, upperFreqBound ); - } - - // estimateAt - // - //! Return an estimate of the fundamental frequency computed - //! at the specified time. The F0Estimate returned stores the - //! estimate of the fundamental frequency (in Hz) and the - //! relative confidence (from 0 to 1) associated with that - //! estimate. - //! - //! \param samps is the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param time is the time in seconds at which to attempt to estimate - //! the fundamental frequency - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \return the estimate of fundamental frequency in Hz and the - //! confidence associated with that estimate (see - //! F0Estimate.h) - - value_type estimateAt( const std::vector< double > & samps, - double sampleRate, - double time, - double lowerFreqBound, double upperFreqBound ) - { - return estimateAt( &samps[0], &samps[0] + samps.size(), sampleRate, - time, lowerFreqBound, upperFreqBound ); - } - - - -// -- spectral analysis parameter access/mutation -- - - //! Return the frequency-domain main lobe width (in Hz measured - //! between zero-crossings) of the analysis window used in spectral - //! analysis. - double windowWidth( void ) const; - - //! Set the frequency-domain main lobe width (in Hz measured - //! between zero-crossings) of the analysis window used in spectral - //! analysis. - //! - //! \param w is the new main lobe width in Hz - void setWindowWidth( double w ); - - - -// -- private auxiliary functions -- - -private: - - // buildSpectrumAnalyzer - // - //! Construct the ReassignedSpectrum that will be used to perform - //! spectral analysis from which peak frequencies and amplitudes - //! will be drawn. This construction is performed in a lazy fashion, - //! and needs to be done again when certain of the parameters change. - //! - //! \param srate is the sampling frequency in Hz, needed to compute - //! analysis window parameters - void buildSpectrumAnalyzer( double srate ); - - - // collectFreqsAndAmps - // - //! Perform spectral analysis on a sequence of samples, using - //! an analysis window centered at the specified time in seconds. - //! Collect the frequencies and amplitudes of the peaks and return - //! them in the vectors provided. - //! - //! \param samps is the beginning of a sequence of samples - //! \param nsamps is the length of the sequence of Partials - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param frequencies is a vector in which to store a sequence of - //! frequencies to be used to estimate the most likely - //! fundamental frequency - //! \param amplitudes is a vector in which to store a sequence of - //! amplitudes to be used to estimate the most likely - //! fundamental frequency - //! \param time is the time in seconds at which to collect frequencies - //! and amplitudes of spectral peaks - - void collectFreqsAndAmps( const double * samps, - unsigned long nsamps, - double sampleRate, - std::vector< double > & frequencies, - std::vector< double > & amplitudes, - double time ); - - -// -- private member variables -- - - std::auto_ptr< ReassignedSpectrum > m_spectrum; - //! the spectrum analyzer - - double m_cacheSampleRate; //! the sample rate used to construct the - - double m_windowWidth; //! the width of the main lobe of the window to - //! be used in spectral analysis, in Hz - -// disallow these until they are implemented - - FundamentalFromSamples( const FundamentalFromSamples & ); - FundamentalFromSamples & operator= ( const FundamentalFromSamples & ); - -}; // end of class FundamentalFromSamples - - - -// --------------------------------------------------------------------------- -// class FundamentalFromPartials -// -//! Class FundamentalFromPartials represents an algorithm for -//! time-varying fundamental frequency estimation from instantaneous -//! Partial amplitudes and frequencies based on a likelihood -//! estimator adapted from Quatieri's Speech Signal Processing text - -class FundamentalFromPartials : public FundamentalEstimator -{ -// -- public interface -- - -public: - -// -- lifecycle -- - - //! Construct a new estimator. - //! - //! The specified precision is used to terminate the iterative - //! estimation procedure. If unspecified, the default value, - //! DefaultPrecisionOver100 * 100 is used. - //! - //! \param precisionHz is the precision in Hz with which the - //! fundamental estimates will be made. - FundamentalFromPartials( double precisionHz = DefaultPrecisionOver100 * 0.01 ); - - - //! Destructor - ~FundamentalFromPartials( void ); - - //! Construct a copy of an estimator. Nothing much to do since this class - //! has no data members. - FundamentalFromPartials( const FundamentalFromPartials & ); - - //! Pass the assignment opertion up to the base class. - FundamentalFromPartials & operator= ( const FundamentalFromPartials & ); - -// -- fundamental frequency estimation -- - - // buildEnvelope - // - //! Construct a linear envelope from fundamental frequency - //! estimates taken at the specified interval in seconds - //! starting at tbeg (seconds) and ending before tend (seconds). - //! - //! \param begin_partials is the beginning of a sequence of Partials - //! \param end_partials is the end of a sequence of Partials - //! \param tbeg is the beginning of the time interval (in seconds) - //! \param tend is the end of the time interval (in seconds) - //! \param interval is the time between breakpoints in the - //! fundamental frequency envelope (in seconds) - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param confidenceThreshold is the minimum confidence level - //! resuired for a fundamental frequency estimate to be - //! added to the envelope. Lower confidence estimates are - //! not added, the envelope returned will not contain - //! breakpoints at times associated with low confidence - //! estimates - //! \return a LinearEnvelope composed of breakpoints corresponding to - //! the fundamental frequency estimates at samples of the span - //! tbeg to tend at the specified sampling interval, only estimates - //! having confidence level exceeding the specified confidence - //! threshold are added to the envelope - LinearEnvelope buildEnvelope( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ); - - // buildEnvelope - // - //! Construct a linear envelope from fundamental frequency - //! estimates taken at the specified interval in seconds - //! starting at tbeg (seconds) and ending before tend (seconds). - //! - //! \param partials is the sequence of Partials - //! \param tbeg is the beginning of the time interval (in seconds) - //! \param tend is the end of the time interval (in seconds) - //! \param interval is the time between breakpoints in the - //! fundamental frequency envelope (in seconds) - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param confidenceThreshold is the minimum confidence level - //! resuired for a fundamental frequency estimate to be - //! added to the envelope. Lower confidence estimates are - //! not added, the envelope returned will not contain - //! breakpoints at times associated with low confidence - //! estimates - //! \return a LinearEnvelope composed of breakpoints corresponding to - //! the fundamental frequency estimates at samples of the span - //! tbeg to tend at the specified sampling interval, only estimates - //! having confidence level exceeding the specified confidence - //! threshold are added to the envelope - LinearEnvelope buildEnvelope( const PartialList & partials, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ) - { - return buildEnvelope( partials.begin(), partials.end(), - tbeg, tend, interval, - lowerFreqBound, upperFreqBound, - confidenceThreshold ); - } - - - // estimateAt - // - //! Return an estimate of the fundamental frequency computed - //! at the specified time. The F0Estimate returned stores the - //! estimate of the fundamental frequency (in Hz) and the - //! relative confidence (from 0 to 1) associated with that - //! estimate. - //! - //! \param begin_partials is the beginning of a sequence of Partials - //! \param end_partials is the end of a sequence of Partials - //! \param time is the time in seconds at which to attempt to estimate - //! the fundamental frequency - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \return the estimate of fundamental frequency in Hz and the - //! confidence associated with that estimate (see - //! F0Estimate.h) - value_type estimateAt( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double time, - double lowerFreqBound, double upperFreqBound ); - - // estimateAt - // - //! Return an estimate of the fundamental frequency computed - //! at the specified time. The F0Estimate returned stores the - //! estimate of the fundamental frequency (in Hz) and the - //! relative confidence (from 0 to 1) associated with that - //! estimate. - //! - //! \param partials is the sequence of Partials - //! \param time is the time in seconds at which to attempt to estimate - //! the fundamental frequency - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \return the estimate of fundamental frequency in Hz and the - //! confidence associated with that estimate (see - //! F0Estimate.h) - value_type estimateAt( const PartialList & partials, - double time, - double lowerFreqBound, double upperFreqBound ) - { - return estimateAt( partials.begin(), partials.end(), - time, - lowerFreqBound, upperFreqBound ); - } - - - -// -- private auxiliary functions -- - -private: - - // collectFreqsAndAmps - // - //! Collect the frequencies and amplitudes of a range of partials - //! at the specified time and return them in the vectors provided. - //! - //! \param begin_partials is the beginning of a sequence of Partials - //! \param end_partials is the end of a sequence of Partials - //! \param frequencies is a vector in which to store a sequence of - //! frequencies to be used to estimate the most likely - //! fundamental frequency - //! \param amplitudes is a vector in which to store a sequence of - //! amplitudes to be used to estimate the most likely - //! fundamental frequency - //! \param time is the time in seconds at which to collect frequencies - //! and amplitudes of the Partials - void collectFreqsAndAmps( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - std::vector< double > & frequencies, - std::vector< double > & amplitudes, - double time ); - - - -}; // end of class FundamentalFromPartials - - - -} // end of namespace Loris - -#endif // ndef INCLUDE_FUNDAMENTAL_H diff --git a/loris_library/Source/include/loris/Harmonifier.h b/loris_library/Source/include/loris/Harmonifier.h deleted file mode 100644 index b1b04d8..0000000 --- a/loris_library/Source/include/loris/Harmonifier.h +++ /dev/null @@ -1,441 +0,0 @@ -#ifndef INCLUDE_HARMONIFIER_H -#define INCLUDE_HARMONIFIER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Harmonifier.h - * - * Definition of class Harmonifier. - * - * Kelly Fitz, 26 Oct 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "Envelope.h" -#include "LorisExceptions.h" -#include "Partial.h" -#include "PartialUtils.h" - -#include // for find -#include // for auto_ptr - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// Class Harmonifier -// -//! A Harmonifier uses a reference frequency envelope to make the -//! frequencies of labeled Partials harmonic. The amount of frequency -//! adjustment can be controlled by a time-varying envelope, and a -//! threshold can be supplied so that only quiet Partials are affected. -// -class Harmonifier -{ -// -- instance variables -- - - Partial _refPartial; //! the Partial whose frequency supplies the - //! reference frequency envelope. - - double _freqFixThresholdDb; //! amplitude threshold below which Partial - //! frequencies are corrected according to - //! a reference Partial, if specified. - - std::auto_ptr< Envelope > _weight; //! weighting function, when 1 harmonic - //! frequencies are used, when 0 breakpoint - //! frequencies are unmodified. - -// -- public interface -- -public: - -// -- lifecycle -- - - //! Construct a new Harmonifier that applies the specified - //! reference Partial to fix the frequencies of Breakpoints - //! whose amplitude is below threshold_dB (0 by default, - //! to apply only to quiet Partials, specify a threshold, - //! like -90). - Harmonifier( const Partial & ref, double threshold_dB = 0 ); - - //! Construct a new Harmonifier that applies the specified - //! reference Partial to fix the frequencies of Breakpoints - //! whose amplitude is below threshold_dB (0 by default, - //! to apply only to quiet Partials, specify a threshold, - //! like -90). The Envelope is a time-varying weighting - //! on the harmonifing process. When 1, harmonic frequencies - //! are used, when 0, breakpoint frequencies are unmodified. - Harmonifier( const Partial & ref, const Envelope & env, - double threshold_dB = 0 ); - - //! Construct a new Harmonifier that applies the specified - //! reference Partial to fix the frequencies of Breakpoints - //! whose amplitude is below threshold_dB (0 by default, - //! to apply only to quiet Partials, specify a threshold, - //! like -90). The reference Partial is the first Partial - //! in the range [b,e) having the specified label. - // - //! \throw InvalidArgument if no Partial in the range [b,e) - //! has the specified label. - // -#if ! defined(NO_TEMPLATE_MEMBERS) - template - Harmonifier( Iter b, Iter e, Partial::label_type refLabel, - double threshold_dB = 0 ); -#else - inline - Harmonifier( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, double threshold_dB = 0 ); -#endif - - //! Construct a new Harmonifier that applies the specified - //! reference Partial to fix the frequencies of Breakpoints - //! whose amplitude is below threshold_dB (0 by default, - //! to apply only to quiet Partials, specify a threshold, - //! like -90). The reference Partial is the first Partial - //! in the range [b,e) having the specified label. - //! - //! The Envelope is a time-varying weighting - //! on the harmonifing process. When 1, harmonic frequencies - //! are used, when 0, breakpoint frequencies are unmodified. - // - //! \throw InvalidArgument if no Partial in the range [b,e) - //! has the specified label. - // -#if ! defined(NO_TEMPLATE_MEMBERS) - template - Harmonifier( Iter b, Iter e, Partial::label_type refLabel, - const Envelope & env, double threshold_dB = 0 ); -#else - inline - Harmonifier( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, const Envelope & env, - double threshold_dB = 0 ); -#endif - - //! Destructor. - ~Harmonifier( void ); - - // use compiler-generated copy and assign. - -// -- operation -- - - //! Apply the reference envelope to a Partial. - void harmonify( Partial & p ) const; - - //! Apply the reference envelope to all Partials in a range. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void harmonify( Iter b, Iter e ); -#else - inline - void harmonify( PartialList::iterator b, PartialList::iterator e ); -#endif - -// -- static members -- - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Harmonifier using as reference the Partial in - //! the specified range labeled refLabel, then apply - //! the instance to all Partials in the range. - //! - //! \param b is the beginning of the range of Partials to harmonify - //! \param e is (one-past) the end of the range of Partials to harmonify - //! \param refLabel is the label of the Partial in [b,e) to - //! use as reference Partial. The reference Partial is the first - //! Partial in the range [b,e) having the specified label. - //! \param threshold_dB is the amplitude below which breakpoint - //! frequencies are harmonified (0 by default, to apply - //! only to quiet Partials, specify a threshold, like -90). - //! - //! \throw InvalidArgument if no Partial in the range [b,e) - //! has the specified label. - //! \throw InvalidArgument if refLabel is non-positive. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - static - void harmonify( Iter b, Iter e, - Partial::label_type refLabel, - double threshold_dB = 0 ); -#else - static inline - void harmonify( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, - double threshold_dB = 0 ); -#endif - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Harmonifier using as reference the Partial in - //! the specified range labeled refLabel, then apply - //! the instance to all Partials in the range. - //! - //! \param b is the beginning of the range of Partials to harmonify - //! \param e is (one-past) the end of the range of Partials to harmonify - //! \param refLabel is the label of the Partial in [b,e) to - //! use as reference Partial. The reference Partial is the first - //! Partial in the range [b,e) having the specified label. - //! \param env is a weighting envelope to apply to the harmonification - //! process: when env is 1, use harmonic frequencies, when env - //! is 0, breakpoint frequencies are unmodified. - //! \param threshold_dB is the amplitude below which breakpoint - //! frequencies are harmonified (0 by default, to apply - //! only to quiet Partials, specify a threshold, like -90). - //! - //! \throw InvalidArgument if no Partial in the range [b,e) - //! has the specified label. - //! \throw InvalidArgument if refLabel is non-positive. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - static - void harmonify( Iter b, Iter e, - Partial::label_type refLabel, - const Envelope & env, double threshold_dB = 0 ); -#else - static inline - void harmonify( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, - const Envelope & env, double threshold_dB = 0 ); -#endif - -private: - -// -- helpers -- - - //! Return the default weighing envelope (always 1). - //! Used in template constructors. - static Envelope * createDefaultEnvelope( void ); - -}; - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Construct a new Harmonifier that applies the specified -//! reference Partial to fix the frequencies of Breakpoints -//! whose amplitude is below threshold_dB (0 by default, -//! to apply only to quiet Partials, specify a threshold, -//! like -90). The reference Partial is the first Partial -//! in the range [b,e) having the specified label. -//! \throw InvalidArgument if no Partial in the range [b,e) -//! has the specified label. -//! \throw InvalidArgument if refLabel is non-positive. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -Harmonifier::Harmonifier( Iter b, Iter e, Partial::label_type refLabel, - double threshold_dB ) : -#else -inline -Harmonifier::Harmonifier( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, double threshold_dB ) : -#endif - _freqFixThresholdDb( threshold_dB ), - _weight( createDefaultEnvelope() ) -{ - if ( 1 > refLabel ) - { - Throw( InvalidArgument, "The reference label must be positive." ); - } - - b = std::find_if( b, e, PartialUtils::isLabelEqual( refLabel ) ); - if ( b == e ) - { - Throw( InvalidArgument, "no Partial has the specified reference label" ); - } - - if ( 0 == b->numBreakpoints() ) - { - Throw( InvalidArgument, - "Cannot use an empty reference Partial in Harmonizer" ); - } - _refPartial = *b; -} - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Construct a new Harmonifier that applies the specified -//! reference Partial to fix the frequencies of Breakpoints -//! whose amplitude is below threshold_dB (0 by default, -//! to apply only to quiet Partials, specify a threshold, -//! like -90). The reference Partial is the first Partial -//! in the range [b,e) having the specified label. -//! -//! The Envelope is a time-varying weighting -//! on the harmonifing process. When 1, harmonic frequencies -//! are used, when 0, breakpoint frequencies are unmodified. -//! -//! \throw InvalidArgument if no Partial in the range [b,e) -//! has the specified label. -//! \throw InvalidArgument if refLabel is non-positive. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -Harmonifier::Harmonifier( Iter b, Iter e, Partial::label_type refLabel, - const Envelope & env, double threshold_dB ) : -#else -inline -Harmonifier::Harmonifier( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, const Envelope & env, - double threshold_dB ) : -#endif - _freqFixThresholdDb( threshold_dB ), - _weight( env.clone() ) -{ - if ( 1 > refLabel ) - { - Throw( InvalidArgument, "The reference label must be positive." ); - } - - b = std::find_if( b, e, PartialUtils::isLabelEqual( refLabel ) ); - if ( b == e ) - { - Throw( InvalidArgument, "no Partial has the specified reference label" ); - } - - if ( 0 == b->numBreakpoints() ) - { - Throw( InvalidArgument, - "Cannot use an empty reference Partial in Harmonizer" ); - } - _refPartial = *b; -} - -// --------------------------------------------------------------------------- -// harmonify -// --------------------------------------------------------------------------- -//! Apply the reference envelope to all Partials in a range. -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Harmonifier::harmonify( Iter b, Iter e ) -#else -inline -void Harmonifier::harmonify( PartialList::iterator b, PartialList::iterator e ) -#endif -{ - while ( b != e ) - { - harmonify( *b ); - ++b; - } -} - -// --------------------------------------------------------------------------- -// harmonify (STATIC) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! Construct a Harmonifier using as reference the Partial in -//! the specified range labeled refLabel, then apply -//! the instance to all Partials in the range. -//! -//! \param b is the beginning of the range of Partials to harmonify -//! \param e is (one-past) the end of the range of Partials to harmonify -//! \param refLabel is the label of the Partial in [b,e) to -//! use as reference Partial. The reference Partial is the first -//! Partial in the range [b,e) having the specified label. -//! \param threshold_dB is the amplitude below which breakpoint -//! frequencies are harmonified (0 by default, to apply -//! only to quiet Partials, specify a threshold, like -90). -//! -//! \throw InvalidArgument if no Partial in the range [b,e) -//! has the specified label. -//! \throw InvalidArgument if refLabel is non-positive. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Harmonifier::harmonify( Iter b, Iter e, - Partial::label_type refLabel, - double threshold_dB ) -#else -inline -void Harmonifier::harmonify( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, - double threshold_dB ) -#endif -{ - Harmonifier instance( b, e, refLabel, threshold_dB ); - instance.harmonify( b, e ); -} - -// --------------------------------------------------------------------------- -// harmonify (STATIC) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! Construct a Harmonifier using as reference the Partial in -//! the specified range labeled refLabel, then apply -//! the instance to all Partials in the range. -//! -//! \param b is the beginning of the range of Partials to harmonify -//! \param e is (one-past) the end of the range of Partials to harmonify -//! \param refLabel is the label of the Partial in [b,e) to -//! use as reference Partial. The reference Partial is the first -//! Partial in the range [b,e) having the specified label. -//! \param env is a weighting envelope to apply to the harmonification -//! process: when env is 1, use harmonic frequencies, when env -//! is 0, breakpoint frequencies are unmodified. -//! \param threshold_dB is the amplitude below which breakpoint -//! frequencies are harmonified (0 by default, to apply -//! only to quiet Partials, specify a threshold, like -90). -//! -//! \throw InvalidArgument if no Partial in the range [b,e) -//! has the specified label. -//! \throw InvalidArgument if refLabel is non-positive. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Harmonifier::harmonify( Iter b, Iter e, - Partial::label_type refLabel, - const Envelope & env, double threshold_dB ) -#else -inline -void Harmonifier::harmonify( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, - const Envelope & env, double threshold_dB ) -#endif -{ - Harmonifier instance( b, e, refLabel, env, threshold_dB ); - instance.harmonify( b, e ); -} - -} // namespace Loris - -#endif /* ndef INCLUDE_HARMONIFIER_H */ diff --git a/loris_library/Source/include/loris/ImportLemur.h b/loris_library/Source/include/loris/ImportLemur.h deleted file mode 100644 index e887e64..0000000 --- a/loris_library/Source/include/loris/ImportLemur.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef INCLUDE_IMPORTLEMUR_H -#define INCLUDE_IMPORTLEMUR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * ImportLemur.h - * - * Definition of class Loris::ImportLemur for importing Partials stored - * in Lemur 5 alpha files. - * - * Kelly Fitz, 10 Sept 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "PartialList.h" -#include "LorisExceptions.h" -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class ImportLemur -// -class ImportLemur -{ -// -- instance variables -- - PartialList _partials; // collect Partials here - -// -- public interface -- -public: -// construction: -// (compiler can generate destructor) - ImportLemur( const std::string & fname, double bweCutoff = 1000 ); - -// PartialList access: - PartialList & partials( void ) { return _partials; } - const PartialList & partials( void ) const { return _partials; } - -// -- unimplemented -- -private: - ImportLemur( const ImportLemur & other ); - ImportLemur & operator = ( const ImportLemur & rhs ); - -}; // end of class ImportLemur - -// --------------------------------------------------------------------------- -// class ImportException -// -// Class of exceptions thrown when there is an error importing -// Partials. -// -class ImportException : public Exception -{ -public: - ImportException( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Import Error -- ").append( str ), where ) {} -}; - -} // end of namespace Loris - -#endif /* ndef INCLUDE_IMPORTLEMUR_H */ diff --git a/loris_library/Source/include/loris/KaiserWindow.h b/loris_library/Source/include/loris/KaiserWindow.h deleted file mode 100644 index d0ba494..0000000 --- a/loris_library/Source/include/loris/KaiserWindow.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef INCLUDE_KAISERWINDOW_H -#define INCLUDE_KAISERWINDOW_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * KaiserWindow.h - * - * Definition of class Loris::KaiserWindow. - * - * Kelly Fitz, 14 Dec 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class KaiserWindow -// -//! Computes samples of a Kaiser window -//! function (see Kaiser and Schafer, 1980) for windowing FFT data. -// -class KaiserWindow -{ -// -- public interface -- -public: - - // -- window building -- - - //! Build a new Kaiser analysis window having the specified shaping - //! parameter. See Oppenheim and Schafer: "Digital Signal Processing" - //! (1975), p. 452 for further explanation of the Kaiser window. Also, - //! see Kaiser and Schafer, 1980. - //! - //! \param win is the vector that will store the window - //! samples. The number of samples computed will be - //! equal to the length of this vector. Any previous - //! contents will be overwritten. - //! \param shape is the Kaiser shaping parameter, controlling - //! the sidelobe rejection level. - static void buildWindow( std::vector< double > & win, double shape ); - - //! Build a new time-derivative Kaiser analysis window having the - //! specified shaping parameter, for computing frequency reassignment. - //! The closed form for the time derivative can be obtained from the - //! property of modified Bessel functions that the derivative of the - //! zeroeth order function is equal to the first order function. - //! - //! \param win is the vector that will store the window - //! samples. The number of samples computed will be - //! equal to the length of this vector. Any previous - //! contents will be overwritten. - //! \param shape is the Kaiser shaping parameter, controlling - //! the sidelobe rejection level. - static void buildTimeDerivativeWindow( std::vector< double > & win, double shape ); - - - // -- window parameter estimation -- - - //! Compute a shaping parameter that will achieve the specified - //! level of sidelobe rejection. - //! - //! \param atten is the desired sidelobe attenuation in - //! positive decibels (e.g. 65 dB) - //! \returns the Kaiser shaping paramater - static double computeShape( double atten ); - - //! Compute the necessary length in samples of a Kaiser window - //! having the specified shaping parameter that has the - //! desired main lobe width. - //! - //! \param width is the desired main lobe width expressed - //! as a fraction of the sample rate. - //! \param alpha is the Kaiser shaping parameter (the - //! main lobe width is influenced primarily by the - //! window length,but also by the shape). - //! \returns the window length in samples - static unsigned long computeLength( double width, double alpha ); - -// construction is not allowed: -private: - KaiserWindow( void ); - -}; // end of class KaiserWindow - -} // end of namespace Loris - -#endif /* ndef INCLUDE_KAISERWINDOW_H */ diff --git a/loris_library/Source/include/loris/LinearEnvelope.h b/loris_library/Source/include/loris/LinearEnvelope.h deleted file mode 100644 index be06f69..0000000 --- a/loris_library/Source/include/loris/LinearEnvelope.h +++ /dev/null @@ -1,303 +0,0 @@ -#ifndef INCLUDE_LINEARENVELOPE_H -#define INCLUDE_LINEARENVELOPE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * LinearEnvelope.h - * - * Definition of class LinearEnvelope. - * - * Kelly Fitz, 23 April 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Envelope.h" -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class LinearEnvelope -// -//! A LinearEnvelope represents a linear segment breakpoint function -//! with infinite extension at each end (that is, evalutaing the -//! envelope past either end of the breakpoint function yields the -//! value at the nearest end point). -//! -//! LinearEnvelope implements the Envelope interface, described -//! by the abstract class Envelope. -//! -//! LinearEnvelope inherits the types -//! \li \c size_type -//! \li \c value_type -//! \li \c iterator -//! \li \c const_iterator -//! -//! and the member functions -//! \li size_type size( void ) const -//! \li bool empty( void ) const -//! \li iterator begin( void ) -//! \li const_iterator begin( void ) const -//! \li iterator end( void ) -//! \li const_iterator end( void ) const -//! -//! from std::map< double, double >. -// -class LinearEnvelope : public Envelope, private std::map< double, double > -{ -// -- public interface -- -public: -// -- construction -- - - //! Construct a new LinearEnvelope having no - //! breakpoints (and an implicit value of 0 everywhere). - LinearEnvelope( void ); - - //! Construct and return a new LinearEnvelope having a - //! single breakpoint at 0 (and an implicit value everywhere) - //! of initialValue. - //! - //! \param initialValue is the value of this LinearEnvelope - //! at time 0. - explicit LinearEnvelope( double initialValue ); - - // compiler-generated copy, assignment, and destruction are OK. - -// -- Envelope interface -- - - //! Return an exact copy of this LinearEnvelope - //! (polymorphic copy, following the Prototype pattern). - virtual LinearEnvelope * clone( void ) const; - - //! Return the linearly-interpolated value of this LinearEnvelope at - //! the specified time. - //! - //! \param t is the time at which to evaluate this - //! LinearEnvelope. - virtual double valueAt( double t ) const; - - -// -- envelope composition -- - - //! Insert a breakpoint representing the specified (time, value) - //! pair into this LinearEnvelope. If there is already a - //! breakpoint at the specified time, it will be replaced with - //! the new breakpoint. - //! - //! \param time is the time at which to insert a new breakpoint - //! \param value is the value of the new breakpoint - void insert( double time, double value ); - - //! Insert a breakpoint representing the specified (time, value) - //! pair into this LinearEnvelope. Same as insert, retained - //! for backwards-compatibility. - //! - //! \param time is the time at which to insert a new breakpoint - //! \param value is the value of the new breakpoint - void insertBreakpoint( double time, double value ) - { insert( time, value ); } - - - //! Add a constant value to this LinearEnvelope and return a reference - //! to self. - //! - //! \param offset is the value to add to all points in the envelope - LinearEnvelope & operator+=( double offset ); - - //! Subtract a constant value from this LinearEnvelope and return a reference - //! to self. - //! - //! \param offset is the value to subtract from all points in the envelope - LinearEnvelope & operator-=( double offset ) - { - return operator+=( -offset ); - } - - //! Scale this LinearEnvelope by a constant value and return a reference - //! to self. - //! - //! \param scale is the value by which to multiply to all points in - //! the envelope - LinearEnvelope & operator*=( double scale ); - - //! Divide this LinearEnvelope by a constant value and return a reference - //! to self. - //! - //! \param div is the value by which to divide to all points in - //! the envelope - LinearEnvelope & operator/=( double div ) - { - return operator*=( 1.0 / div ); - } - -// -- interface inherited from std::map -- - - using std::map< double, double >::size; - using std::map< double, double >::empty; - using std::map< double, double >::clear; - using std::map< double, double >::begin; - using std::map< double, double >::end; - using std::map< double, double >::size_type; - using std::map< double, double >::value_type; - using std::map< double, double >::iterator; - using std::map< double, double >::const_iterator; - -}; // end of class LinearEnvelope - - -// -- binary operators (inline nonmembers) -- - -//! Add a constant value to a LinearEnvelope and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator+( LinearEnvelope env, double offset ) -{ - env += offset; - return env; -} - -//! Add a constant value to a LinearEnvelope and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator+( double offset, LinearEnvelope env ) -{ - env += offset; - return env; -} - -//! Add two LinearEnvelopes and return a new LinearEnvelope. -inline -LinearEnvelope operator+( const LinearEnvelope & e1, const LinearEnvelope & e2 ) -{ - LinearEnvelope ret; - - // For each breakpoint in e1, insert a breakpoint having a value - // equal to the sum of the two envelopes at that time. - for ( LinearEnvelope::const_iterator it = e1.begin(); it != e1.end(); ++it ) - { - double t = it->first; - double v = it->second; - - ret.insert( t, v + e2.valueAt( t ) ); - } - - // For each breakpoint in e2, insert a breakpoint having a value - // equal to the sum of the two envelopes at that time. - for ( LinearEnvelope::const_iterator it = e2.begin(); it != e2.end(); ++it ) - { - double t = it->first; - double v = it->second; - - ret.insert( t, v + e1.valueAt( t ) ); - } - - return ret; -} - -//! Subtract a constant value from a LinearEnvelope and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator-( LinearEnvelope env, double offset ) -{ - env -= offset; - return env; -} - -//! Subtract a LinearEnvelope from a constant value and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator-( double offset, LinearEnvelope env ) -{ - env *= -1.0; - env += offset; - return env; -} - -//! Subtract two LinearEnvelopes and return a new LinearEnvelope. -inline -LinearEnvelope operator-( const LinearEnvelope & e1, const LinearEnvelope & e2 ) -{ - LinearEnvelope ret; - - // For each breakpoint in e1, insert a breakpoint having a value - // equal to the difference between the two envelopes at that time. - for ( LinearEnvelope::const_iterator it = e1.begin(); it != e1.end(); ++it ) - { - double t = it->first; - double v = it->second; - - ret.insert( t, v - e2.valueAt( t ) ); - } - - // For each breakpoint in e2, insert a breakpoint having a value - // equal to the difference between the two envelopes at that time. - for ( LinearEnvelope::const_iterator it = e2.begin(); it != e2.end(); ++it ) - { - double t = it->first; - double v = it->second; - - ret.insert( t, e1.valueAt( t ) - v ); - } - - return ret; -} - -//! Scale a LinearEnvelope by a constant value and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator*( LinearEnvelope env, double scale ) -{ - env *= scale; - return env; -} - -//! Scale a LinearEnvelope by a constant value and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator*( double scale, LinearEnvelope env ) -{ - env *= scale; - return env; -} - -//! Divide a LinearEnvelope by a constant value and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator/( LinearEnvelope env, double div ) -{ - env /= div; - return env; -} - -//! Divide constant value by a LinearEnvelope and return a new -//! LinearEnvelope. No shortcut implementation for this one, -//! don't inline. -LinearEnvelope operator/( double scale, LinearEnvelope env ); - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_LINEARENVELOPE_H */ diff --git a/loris_library/Source/include/loris/LorisExceptions.h b/loris_library/Source/include/loris/LorisExceptions.h deleted file mode 100644 index d0537e0..0000000 --- a/loris_library/Source/include/loris/LorisExceptions.h +++ /dev/null @@ -1,308 +0,0 @@ -#ifndef INCLUDE_EXCEPTIONS_H -#define INCLUDE_EXCEPTIONS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * LorisExceptions.h - * - * Definition of class Exception, a generic exception class, and - * commonly-used derived exception classes. - * - * This file was formerly called Exception.h, but that filename caused build - * problems on case-insensitive systems that sometimes had system headers - * called exception.h. - * - * Kelly Fitz, 17 Oct 2006 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Exception -// -//! Exception is a generic exception class for reporting exceptional -//! circumstances in Loris. Exception is derived from std:exception, -//! and is the base for a hierarchy of derived exception classes -//! in Loris. -//! -// -class Exception : public std::exception -{ -// -- public interface -- -public: -// --- lifecycle --- - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - Exception( const std::string & str, const std::string & where = "" ); - - //! Destroy this Exception. - virtual ~Exception( void ) throw() - { - } - -// --- access/mutation --- - - //! Return a description of this Exception in the form of a - //! C-style string (char pointer). Overrides std::exception::what. - //! - //! \return a C-style string describing the exceptional condition. - const char * what( void ) const throw() { return _sbuf.c_str(); } - - //! Append the specified string to this Exception's description, - //! and return a reference to this Exception. - //! - //! \param str is text to append to the exception description - //! \return a reference to this Exception. - Exception & append( const std::string & str ); - - //! Return a read-only refernce to this Exception's - //! description string. - //! - //! \return a string describing the exceptional condition - const std::string & str( void ) const - { - return _sbuf; - } - -// -- instance variables -- -protected: - - //! string for storing the exception description - std::string _sbuf; - -}; // end of class Exception - -// --------------------------------------------------------------------------- -// class AssertionFailure -// -//! Class of exceptions thrown when an assertion (usually representing an -//! invariant condition, and usually detected by the Assert macro) is -//! violated. -// -class AssertionFailure : public Exception -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - AssertionFailure( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Assertion failed -- ").append( str ), where ) - { - } - -}; // end of class AssertionFailure - -// --------------------------------------------------------------------------- -// class IndexOutOfBounds -// -//! Class of exceptions thrown when a subscriptable object is accessed -//! with an index that is out of range. -// -class IndexOutOfBounds : public Exception -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - IndexOutOfBounds( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Index out of bounds -- ").append( str ), where ) {} - -}; // end of class IndexOutOfBounds - - -// --------------------------------------------------------------------------- -// class InvalidObject -// -//! Class of exceptions thrown when an object is found to be badly configured -//! or otherwise invalid. -// -class InvalidObject : public Exception -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - InvalidObject( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Invalid configuration or object -- ").append( str ), where ) - { - } - -}; // end of class InvalidObject - -// --------------------------------------------------------------------------- -// class InvalidIterator -// -//! Class of exceptions thrown when an Iterator is found to be badly configured -//! or otherwise invalid. -// -class InvalidIterator : public InvalidObject -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - InvalidIterator( const std::string & str, const std::string & where = "" ) : - InvalidObject( std::string("Invalid Iterator -- ").append( str ), where ) - { - } - -}; // end of class InvalidIterator - -// --------------------------------------------------------------------------- -// class InvalidArgument -// -//! Class of exceptions thrown when a function argument is found to be invalid. -// -class InvalidArgument : public Exception -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - InvalidArgument( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Invalid Argument -- ").append( str ), where ) - { - } - -}; // end of class InvalidArgument - -// --------------------------------------------------------------------------- -// class RuntimeError -// -//! Class of exceptions thrown when an unanticipated runtime error is -//! encountered. -// -class RuntimeError : public Exception -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - RuntimeError( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Runtime Error -- ").append( str ), where ) - { - } - -}; // end of class RuntimeError - -// --------------------------------------------------------------------------- -// class FileIOException -// -//! Class of exceptions thrown when file input or output fails. -// -class FileIOException : public RuntimeError -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - FileIOException( const std::string & str, const std::string & where = "" ) : - RuntimeError( std::string("File i/o error -- ").append( str ), where ) - { - } - -}; // end of class FileIOException - -// --------------------------------------------------------------------------- -// macros for throwing exceptions -// -// The compelling reason for using macros instead of inlines for all these -// things is that the __FILE__ and __LINE__ macros will be useful. -// -#define __STR(x) __VAL(x) -#define __VAL(x) #x -#define Throw( exType, report ) \ - throw exType( report, " ( " __FILE__ " line: " __STR(__LINE__) " )" ) - -#define Assert(test) \ - do { \ - if (!(test)) Throw( Loris::AssertionFailure, #test ); \ - } while (false) - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_EXCEPTIONS_H */ diff --git a/loris_library/Source/include/loris/Marker.h b/loris_library/Source/include/loris/Marker.h deleted file mode 100644 index 6c51a23..0000000 --- a/loris_library/Source/include/loris/Marker.h +++ /dev/null @@ -1,178 +0,0 @@ -#ifndef INCLUDE_MARKER_H -#define INCLUDE_MARKER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Marker.h - * - * Definition of classes Marker and MarkerContainer representing labeled - * time points or temporal features in imported and exported data. Used by - * file I/O classes AiffFile, SdifFile, and SpcFile. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Marker -// -//! Class Marker represents a labeled time point in a set of Partials -//! or a vector of samples. Collections of Markers (see the MarkerContainer -//! definition below) are held by the File I/O classes in Loris (AiffFile, -//! SdifFile, and SpcFile) to identify temporal features in imported -//! and exported data. -// -class Marker -{ -// -- public interface -- -public: -// -- construction -- - - //! Default constructor - initialize a Marker at time zero with no label. - Marker( void ); - - //! Initialize a Marker with the specified time (in seconds) and name. - //! - //! \param t is the time associated with the new Marker - //! \param s is the name associated with the new Marker - Marker( double t, const std::string & s ); - - //! Initialize a Marker that is an exact copy of another Marker, that is, - //! having the same time and name. - //! - //! \param other is the Marker to copy from - Marker( const Marker & other ); - - //! Make this Marker an exact copy, having the same time and name, - //! as the Marker rhs. - //! - //! \param rhs is the Marker to assign from - //! \return reference to self - Marker & operator=( const Marker & rhs ); - -// -- comparison -- - - //! Return true if this Marker must appear earlier than rhs in a sorted - //! collection of Markers, and false otherwise. - //! (Markers are sorted by time.) - //! - //! \param rhs is the Marker to compare with this Marker - //! \return true if this Marker's time is earlier than that of - //! rhs, otherwise false - bool operator< ( const Marker & rhs ) const; - -// -- access -- - - //! Return a reference to the name string - //! for this Marker. - std::string & name( void ); - - //! Return a const reference to the name string - //! for this Marker. - const std::string & name( void ) const; - - //! Return the time (in seconds) associated with this Marker. - double time( void ) const; - - -// -- mutation -- - //! Set the name of the Marker. - void setName( const std::string & s ); - - //! Set the time (in seconds) associated with this Marker. - void setTime( double t ); - -// -- comparitors -- - - //! Comparitor (binary) functor returning true if its first Marker - //! argument should appear before the second in a range sorted - //! by Marker name. - struct compareNameLess : - public std::binary_function< const Marker, const Marker, bool > - { - //! Function call operator, return true if the first Marker - //! argument should appear before the second in a range sorted - //! by Marker name. - bool operator()( const Marker & lhs, const Marker & rhs ) const - { return lhs.name() < rhs.name(); } - }; - - //! old name for compareNameLess, legacy support - //! \deprecated Use compareNameLess instead. - typedef compareNameLess sortByName; - - - //! Comparitor (binary) functor returning true if its first Marker - //! argument should appear before the second in a range sorted - //! by Marker time. - struct compareTimeLess : - public std::binary_function< const Marker, const Marker, bool > - { - //! Function call operator, return true if the first Marker - //! argument should appear before the second in a range sorted - //! by Marker time. - bool operator()( const Marker & lhs, const Marker & rhs ) const - { return lhs.time() < rhs.time(); } - }; - - //! old name for compareTimeLess, legacy support - //! \deprecated Use compareTimeLess instead - typedef compareTimeLess sortByTime; - - //! Predicate functor returning true if the name of a Marker - //! equal to the specified string, and false otherwise. - class isNameEqual : public std::unary_function< const Marker, bool > - { - public: - //! Initialize a new instance with the specified name. - isNameEqual( const std::string & s ) : name(s) {} - - //! Function call operator: evaluate a Marker. - bool operator()( const Marker & m ) const - { return m.name() == name; } - - private: - std::string name; //! the name to compare against - }; - -private: - -// -- implementation -- - - double m_time; //! the time in seconds associated with the Marker - std::string m_name; //! the name of the Marker - -}; // end of class Marker - -} // end of namespace Loris - -#endif /* ndef INCLUDE_MARKER_H */ diff --git a/loris_library/Source/include/loris/Morpher.h b/loris_library/Source/include/loris/Morpher.h deleted file mode 100644 index a291cac..0000000 --- a/loris_library/Source/include/loris/Morpher.h +++ /dev/null @@ -1,590 +0,0 @@ -#ifndef INCLUDE_MORPHER_H -#define INCLUDE_MORPHER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Morpher.h - * - * Definition of class Morpher. - * - * Kelly Fitz, 15 Oct 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "PartialList.h" -#include "Partial.h" - -#include // for auto_ptr - -// begin namespace -namespace Loris { - -class Envelope; - -// --------------------------------------------------------------------------- -// Class Morpher -// -//! Class Morpher performs sound morphing and Partial parameter -//! envelope interpolation according to a trio of frequency, amplitude, -//! and bandwidth morphing functions, described by Envelopes. -//! Sound morphing is achieved by interpolating the time-varying -//! frequencies, amplitudes, and bandwidths of corresponding partials -//! obtained from reassigned bandwidth-enhanced analysis of the source -//! and target sounds. Partial correspondences may be established by -//! labeling, using instances of the Channelizer and Distiller classes. -//! -//! The Morpher collects morphed Partials in a PartialList, that is -//! accessible to clients. -//! -//! For more information about sound morphing using -//! the Reassigned Bandwidth-Enhanced Additive Sound -//! Model, refer to the Loris website: -//! www.cerlsoundgroup.org/Loris/. -//! -//! Morpher is a leaf class, do not subclass. -// -class Morpher -{ -// -- instance variables -- - - std::auto_ptr< Envelope > _freqFunction; //! frequency morphing function - std::auto_ptr< Envelope > _ampFunction; //! amplitude morphing function - std::auto_ptr< Envelope > _bwFunction; //! bandwidth morphing function - - PartialList _partials; //! collect Partials here - - Partial _srcRefPartial; //! reference Partials - Partial _tgtRefPartial; //! for source and target sounds when - //! morphing sequences of labeled Partials, - //! default (empty Partial) implies no - //! reference Partial is used - - double _freqFixThresholdDb; //! amplitude threshold below which Partial - //! frequencies are corrected according to - //! a reference Partial, if specified. - - double _logMorphShape; //! shaping parameter that controls the - //! shape of the logarithmic morphing function, - //! mostly when one of the source values - //! is equal to zero. - //! Only relevant when _doLogAmpMorphing is true. - //! - //! Don't use this for anything, just leave it - //! at the default. - - double _minBreakpointGapSec; //! the minimum time gap between two Breakpoints - //! in the morphed Partials. Morphing two - //! Partials can generate a third Partial having - //! Breakpoints arbitrarily close together in time, - //! and this makes morphs huge. Raising this - //! threshold limits the Breakpoint density in - //! the morphed Partials. - //! Default is 1/10 ms. - - - bool _doLogAmpMorphing; //! if true (default), amplitudes and bandwidths - //! are morphed in the log domain, if false they - //! are morphed in the linear domain. - - bool _doLogFreqMorphing; //! if true, frequencies are morphed in the log - //! domain, if false (default) they are morphed - //! in the linear domain. - - -// -- public interface -- -public: -// -- construction -- - - //! Construct a new Morpher using the same morphing envelope for - //! frequency, amplitude, and bandwidth (noisiness). - //! - //! \param f is the Envelope to clone for all three morphing - //! functions. - Morpher( const Envelope & f ); - - //! Construct a new Morpher using the specified morphing envelopes for - //! frequency, amplitude, and bandwidth (noisiness). - //! - //! \param ff is the Envelope to clone for the frequency morphing function - //! \param af is the Envelope to clone for the amplitude morphing function - //! \param bwf is the Envelope to clone for the bandwidth morphing function - Morpher( const Envelope & ff, const Envelope & af, const Envelope & bwf ); - - //! Construct a new Morpher that is a duplicate of rhs. - //! - //! \param rhs is the Morpher to duplicate - Morpher( const Morpher & rhs ); - - //! Destroy this Morpher. - ~Morpher( void ); - - //! Make this Morpher a duplicate of rhs. - //! - //! \param rhs is the Morpher to duplicate - Morpher & operator= ( const Morpher & rhs ); - -// -- morphed parameter computation -- - -// -- Partial morphing -- - - //! Morph a pair of Partials to yield a new morphed Partial. - //! Dummy Partials (having no Breakpoints) don't contribute to the - //! morph, except to cause their opposite to fade out. - //! Either (or neither) the source or target Partial may be a dummy - //! Partial (no Breakpoints), but not both. The morphed - //! Partial has Breakpoints at times corresponding to every Breakpoint - //! in both source Partials, omitting Breakpoints that would be - //! closer than the minBreakpointGap to their predecessor. - //! The new morphed Partial is assigned the specified label and returned. - //! - //! \param src is the Partial corresponding to a morph function - //! value of 0, evaluated at the specified time. - //! \param tgt is the Partial corresponding to a morph function - //! value of 1, evaluated at the specified time. - //! \param assignLabel is the label assigned to the morphed Partial - //! \return the morphed Partial - Partial morphPartials( Partial src, Partial tgt, int assignLabel ); - - //! Bad legacy name for morphPartials. - //! \deprecated Use morphPartials instead. - Partial morphPartial( Partial src, Partial tgt, int assignLabel ) - { return morphPartials( src, tgt, assignLabel ); } - - //! Morph two sounds (collections of Partials labeled to indicate - //! correspondences) into a single labeled collection of Partials. - //! Unlabeled Partials (having label 0) are crossfaded. The morphed - //! and crossfaded Partials are stored in the Morpher's PartialList. - //! - //! The Partials in the first range are treated as components of the - //! source sound, corresponding to a morph function value of 0, and - //! those in the second are treated as components of the target sound, - //! corresponding to a morph function value of 1. - //! - //! \sa crossfade, morphPartials - //! - //! \param beginSrc is the beginning of the sequence of Partials - //! corresponding to a morph function value of 0. - //! \param endSrc is (one past) the end of the sequence of Partials - //! corresponding to a morph function value of 0. - //! \param beginTgt is the beginning of the sequence of Partials - //! corresponding to a morph function value of 1. - //! \param endTgt is (one past) the end of the sequence of Partials - //! corresponding to a morph function value of 1. - void morph( PartialList::const_iterator beginSrc, - PartialList::const_iterator endSrc, - PartialList::const_iterator beginTgt, - PartialList::const_iterator endTgt ); - - //! Crossfade Partials with no correspondences. - //! - //! Unlabeled Partials (having the specified label) are considered to - //! have no correspondences, so they are just faded out, and not - //! actually morphed. Consistent with the morphing behavior, - //! crossfaded Partials are thinned, if necssary, so that no - //! two Breakpoints are closer in time than the minBreakpointGap. - //! - //! The Partials in the first range are treated as components of the - //! source sound, corresponding to a morph function value of 0, and - //! those in the second are treated as components of the target sound, - //! corresponding to a morph function value of 1. - //! - //! The crossfaded Partials are stored in the Morpher's PartialList. - //! - //! \param beginSrc is the beginning of the sequence of Partials - //! corresponding to a morph function value of 0. - //! \param endSrc is (one past) the end of the sequence of Partials - //! corresponding to a morph function value of 0. - //! \param beginTgt is the beginning of the sequence of Partials - //! corresponding to a morph function value of 1. - //! \param endTgt is (one past) the end of the sequence of Partials - //! corresponding to a morph function value of 1. - //! \param label is the label to associate with unlabeled - //! Partials (default is 0). - void crossfade( PartialList::const_iterator beginSrc, - PartialList::const_iterator endSrc, - PartialList::const_iterator beginTgt, - PartialList::const_iterator endTgt, - Partial::label_type label = 0 ); - - - //! Compute morphed parameter values at the specified time, using - //! the source and target Breakpoints (assumed to correspond exactly - //! to the specified time). - //! - //! \param srcBkpt is the Breakpoint corresponding to a morph function - //! value of 0. - //! \param tgtBkpt is the Breakpoint corresponding to a morph function - //! value of 1. - //! \param time is the time corresponding to srcBkpt (used - //! to evaluate the morphing functions and tgtPartial). - //! \return the morphed Breakpoint - // - Breakpoint - morphBreakpoints( Breakpoint srcBkpt, Breakpoint tgtBkpt, - double time ) const; - - //! Compute morphed parameter values at the specified time, using - //! the source Breakpoint (assumed to correspond exactly to the - //! specified time) and the target Partial (whose parameters are - //! examined at the specified time). - //! - //! DEPRECATED do not use. - //! - //! \pre the target Partial may not be a dummy Partial (no Breakpoints). - //! - //! \param bp is the Breakpoint corresponding to a morph function - //! value of 0. - //! \param tgtPartial is the Partial corresponding to a morph function - //! value of 1, evaluated at the specified time. - //! \param time is the time corresponding to srcBkpt (used - //! to evaluate the morphing functions and tgtPartial). - //! \return the morphed Breakpoint - Breakpoint - morphSrcBreakpoint( const Breakpoint & bp, const Partial & tgtPartial, - double time ) const; - - //! Compute morphed parameter values at the specified time, using - //! the target Breakpoint (assumed to correspond exactly to the - //! specified time) and the source Partial (whose parameters are - //! examined at the specified time). - //! - //! DEPRECATED do not use. - //! - //! \pre the source Partial may not be a dummy Partial (no Breakpoints). - //! - //! \param bp is the Breakpoint corresponding to a morph function - //! value of 1. - //! \param srcPartial is the Partial corresponding to a morph function - //! value of 0, evaluated at the specified time. - //! \param time is the time corresponding to srcBkpt (used - //! to evaluate the morphing functions and tgtPartial). - //! \return the morphed Breakpoint - Breakpoint - morphTgtBreakpoint( const Breakpoint & bp, const Partial & srcPartial, - double time ) const; - - //! Compute morphed parameter values at the specified time, using - //! the source Breakpoint, assumed to correspond exactly to the - //! specified time, and assuming that there is no corresponding - //! target Partial, so the source Breakpoint should be simply faded. - //! - //! \param bp is the Breakpoint corresponding to a morph function - //! value of 0. - //! \param time is the time corresponding to bp (used - //! to evaluate the morphing functions). - //! \return the faded Breakpoint - Breakpoint fadeSrcBreakpoint( Breakpoint bp, double time ) const; - - //! Compute morphed parameter values at the specified time, using - //! the target Breakpoint, assumed to correspond exactly to the - //! specified time, and assuming that there is not corresponding - //! source Partial, so the target Breakpoint should be simply faded. - //! - //! \param bp is the Breakpoint corresponding to a morph function - //! value of 1. - //! \param time is the time corresponding to bp (used - //! to evaluate the morphing functions). - //! \return the faded Breakpoint - Breakpoint fadeTgtBreakpoint( Breakpoint bp, double time ) const; - -// -- morphing function access/mutation -- - - //! Assign a new frequency morphing envelope to this Morpher. - void setFrequencyFunction( const Envelope & f ); - - //! Assign a new amplitude morphing envelope to this Morpher. - void setAmplitudeFunction( const Envelope & f ); - - //! Assign a new bandwidth morphing envelope to this Morpher. - void setBandwidthFunction( const Envelope & f ); - - //! Return a reference to this Morpher's frequency morphing envelope. - const Envelope & frequencyFunction( void ) const; - - //! Return a reference to this Morpher's amplitude morphing envelope. - const Envelope & amplitudeFunction( void ) const; - - //! Return a reference to this Morpher's bandwidth morphing envelope. - const Envelope & bandwidthFunction( void ) const; - - //! Return the shaping parameter for the amplitude moprhing - //! function (only used in log-amplitude morphing). - //! - //! DEPRECATED - double amplitudeShape( void ) const; - - //! Set the shaping parameter for the amplitude moprhing - //! function (only used in log-amplitude morphing). - //! Only relevant when _doLogAmpMorphing is true. - //! Don't use this for anything, just leave it - //! at the default. - //! - //! DEPRECATED - void setAmplitudeShape( double x ); - - //! Enable (or disable) log-domain amplitude and bandwidth morphing. - //! Default is true. - void enableLogAmpMorphing( bool enable = true ) { _doLogAmpMorphing = enable; } - - //! Enable (or disable) log-domain frequency morphing. - //! Default is false. - void enableLogFreqMorphing( bool enable = true ) { _doLogFreqMorphing = enable; } - - - //! Return the minimum time gap (secs) between two Breakpoints - //! in the morphed Partials. Morphing two - //! Partials can generate a third Partial having - //! Breakpoints arbitrarily close together in time, - //! and this makes morphs huge. Raising this - //! threshold limits the Breakpoint density in - //! the morphed Partials. Default is 1/10 ms. - double minBreakpointGap( void ) const; - - //! Set the minimum time gap (secs) between two Breakpoints - //! in the morphed Partials. Morphing two - //! Partials can generate a third Partial having - //! Breakpoints arbitrarily close together in time, - //! and this makes morphs huge. Raising this - //! threshold limits the Breakpoint density in - //! the morphed Partials. Default is 1/10 ms. - //! - //! \param x is the new minimum gap in seconds, it must be - //! positive - //! \throw InvalidArgument if the specified gap is not positive - void setMinBreakpointGap( double x ); - - -// -- reference Partial label access/mutation -- - - //! Return the Partial to be used as a reference - //! Partial for the source sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference Partial - //! should be used for the source sequence. - const Partial & sourceReferencePartial( void ) const; - - //! Return the Partial to be used as a reference - //! Partial for the source sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference Partial - //! should be used for the source sequence. - Partial & sourceReferencePartial( void ); - - //! Return the Partial to be used as a reference - //! Partial for the target sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference Partial - //! should be used for the target sequence. - const Partial & targetReferencePartial( void ) const; - - //! Return the Partial to be used as a reference - //! Partial for the target sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference Partial - //! should be used for the target sequence. - Partial & targetReferencePartial( void ); - - //! Specify the Partial to be used as a reference - //! Partial for the source sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! The specified Partial must be labeled with its harmonic number. - //! A default (empty) Partial indicates that no reference - //! Partial should be used for the source sequence. - void setSourceReferencePartial( const Partial & p = Partial() ); - - //! Specify the Partial to be used as a reference - //! Partial for the source sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference - //! Partial should be used for the source sequence. - //! - //! \param partials a sequence of Partials to search - //! for the reference Partial - //! \param refLabel the label of the Partial in partials - //! that should be selected as the reference - void setSourceReferencePartial( const PartialList & partials, - Partial::label_type refLabel ); - - //! Specify the Partial to be used as a reference - //! Partial for the target sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! The specified Partial must be labeled with its harmonic number. - //! A default (empty) Partial indicates that no reference - //! Partial should be used for the target sequence. - void setTargetReferencePartial( const Partial & p = Partial() ); - - //! Specify the Partial to be used as a reference - //! Partial for the target sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference - //! Partial should be used for the target sequence. - //! - //! \param partials a sequence of Partials to search - //! for the reference Partial - //! \param refLabel the label of the Partial in partials - //! that should be selected as the reference - void setTargetReferencePartial( const PartialList & partials, - Partial::label_type refLabel ); - -// -- PartialList access -- - - //! Return a reference to this Morpher's list of morphed Partials. - PartialList & partials( void ); - - //! Return a const reference to this Morpher's list of morphed Partials. - const PartialList & partials( void ) const; - -// -- global morphing defaults and constants -- - - //! Amplitude threshold (dB) below which - //! Partial frequencies are corrected using - //! the reference Partial frequency envelope - //! (if specified). - static const double DefaultFixThreshold; - - //! Default amplitude shaping parameter, used in - //! interpolateLogAmplitudes to perform logarithmic - //! amplitude morphs. - //! - //! Compile Loris with LINEAR_AMP_MORPHS defined for - //! legacy-style linear amplitude morphs by default. - //! - //! Change from default using setAmplitudeShape. - static const double DefaultAmpShape; - - //! Default minimum time (sec) between Breakpoints in - //! morphed Partials. - //! Change from default using setMinBreakpointGap. - static const double DefaultBreakpointGap; - -private: - -// -- helper -- - - // PartialCorrespondence represents a map from non-zero Partial - // labels to pairs of pointers to Partials that should be morphed - // into a single Partial that is assigned that label. - // MorphingPair is a pair of pointers to Partials that are - // initialized to zero, and it is the element type for the - // PartialCorrespondence map. - struct MorphingPair - { - Partial src; - Partial tgt; - }; - typedef std::map< Partial::label_type, MorphingPair > PartialCorrespondence; - - //! Helper function that performs the morph between corresponding pairs - //! of Partials identified in a PartialCorrespondence. Called by the - //! morph() implementation accepting two sequences of Partials. - void morph_aux( PartialCorrespondence & correspondence ); - - //! Compute morphed parameter values at the specified time, using - //! the source Breakpoint (assumed to correspond exactly to the - //! specified time) and the target Partial (whose parameters are - //! examined at the specified time). Append the morphed Breakpoint - //! to newp only if the target should contribute to the morph at - //! the specified time. - //! - //! \pre the target Partial may not be a dummy Partial (no Breakpoints). - //! - //! \param srcBkpt is the Breakpoint corresponding to a morph function - //! value of 0. - //! \param tgtPartial is the Partial corresponding to a morph function - //! value of 1, evaluated at the specified time. - //! \param time is the time corresponding to srcBkpt (used - //! to evaluate the morphing functions and tgtPartial). - //! \param newp is the morphed Partial under construction, the morphed - //! Breakpoint is added to this Partial. - // - void appendMorphedSrc( Breakpoint srcBkpt, const Partial & tgtPartial, - double time, Partial & newp ); - - //! Compute morphed parameter values at the specified time, using - //! the target Breakpoint (assumed to correspond exactly to the - //! specified time) and the source Partial (whose parameters are - //! examined at the specified time). Append the morphed Breakpoint - //! to newp only if the target should contribute to the morph at - //! the specified time. - //! - //! \pre the source Partial may not be a dummy Partial (no Breakpoints). - //! - //! \param tgtBkpt is the Breakpoint corresponding to a morph function - //! value of 1. - //! \param srcPartial is the Partial corresponding to a morph function - //! value of 0, evaluated at the specified time. - //! \param time is the time corresponding to srcBkpt (used - //! to evaluate the morphing functions and srcPartial). - //! \param newp is the morphed Partial under construction, the morphed - //! Breakpoint is added to this Partial. - // - void appendMorphedTgt( Breakpoint tgtBkpt, const Partial & srcPartial, - double time, Partial & newp ); - - - //! Parameterinterpolation helpers. - Breakpoint - interpolateParameters( const Breakpoint & srcBkpt, const Breakpoint & tgtBkpt, - double fweight, double aweight, double bweight ) const; - - double interpolateAmplitude( double srcAmp, double tgtAmp, double alpha ) const; - double interpolateBandwidth( double srcBw, double tgtBw, double alpha ) const; - double interpolateFrequency( double srcFreq, double tgtFreq, double alpha ) const; - double interpolatePhase( double srcphase, double tgtphase, double alpha ) const; - - - // Recompute phases for a morphed Partial, so that the synthesized phases - // match the source phases as closesly as possible at times when the - // frequency morphing function is equal to 0 or 1. - void fixMorphedPhases( Partial & newp ) const; - -}; // end of class Morpher - -} // end of namespace Loris - -#endif /* ndef INCLUDE_MORPHER_H */ diff --git a/loris_library/Source/include/loris/NoiseGenerator.h b/loris_library/Source/include/loris/NoiseGenerator.h deleted file mode 100644 index 95ddccd..0000000 --- a/loris_library/Source/include/loris/NoiseGenerator.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef NOISEGENERATOR_H -#define NOISEGENERATOR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * NoiseGenerator.h - * - * Definition of a class representing a gaussian noise generator, filtered and - * used as a modulator in bandwidth-enhanced synthesis. - * - * Kelly Fitz, 5 June 2003 - * revised 11 October 2009 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class NoiseGenerator -// -class NoiseGenerator -{ -// --- interface --- - -public: - - //! Create a new noise generator with the (optionally) specified - //! seed (default is 1.0). - //! - //! \param initSeed is the initial seed for the random number generator - explicit NoiseGenerator( double initSeed = 1.0 ); - - - // copy and assign are free - - - //! Re-seed the random number generator. - //! - //! \param newSeed is the new seed for the random number generator - void seed( double newSeed ); - - // sample - // - //! Generate and return a new sample of Gaussian noise having zero - //! mean and unity standard deviation. Approximate the normal distribution - //! using the Box-Muller transformation applied to a uniform random number - //! generator taken from "Random Number Generators: Good Ones Are Hard To Find," - //! Stephen Park and Keith Miller, Communications of the ACM, October 1988, - //! vol. 31, Number 10. - double sample( void ); - - //! Function call operator, same as calling sample(). - //! - //! \sa sample - double operator() ( void ) { return sample(); } - - -// --- implementation --- -private: - - // random number generation helpers - inline double uniform( void ); - inline double gaussian_normal( void ); - - - // random number generator state variables - double m_useed; - double m_gset; - bool m_iset; - -}; - - -} // end of namespace Loris - -#endif /* ndef NOISEGENERATOR_H */ diff --git a/loris_library/Source/include/loris/Notifier.h b/loris_library/Source/include/loris/Notifier.h deleted file mode 100644 index c0269f2..0000000 --- a/loris_library/Source/include/loris/Notifier.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef INCLUDE_NOTIFIER_H -#define INCLUDE_NOTIFIER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Notifier.h - * - * A pair of dedicated streams, notifier and debugger, are used for - * notification throughout the Loris class library. These streams are used - * like cout or cerr, but they buffer their contents until a newline is - * receieved. Then they post their entire contents to a notification - * handler. The default handler just prints to stderr, but other handlers - * may be dynamically specified using setNotifierHandler() and - * setDebuggerHandler(). - * - * debugger is enabled only when compiled with the preprocessor macro - * Debug_Loris defined. It cannot be enabled using setDebuggerHandler() if - * Debug_Loris is undefined.When Debug_Loris is not defined, characters - * streamed onto debugger are never posted nor are they otherwise - * accessible. - * - * Notifier.h may be included in c files. The stream declarations are - * omitted, but the notification handler routines are accessible. - * - * - * Kelly Fitz, 28 Feb 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - - -/* - * stream declaration, C++ only: - */ -#ifdef __cplusplus - -#include - -// begin namespace -namespace Loris { - -std::ostream & getNotifierStream(void); -std::ostream & getDebuggerStream(void); - -// declare streams: -static std::ostream & notifier = getNotifierStream(); -/* This stream is used throughout Loris (and may be used by clients) - to provide user feedback. Characters streamed onto notifier are - buffered until a newline is received, and then the entire contents - of the stream are flushed to the current notification handler (stderr, - by default). - */ - -static std::ostream & debugger = getDebuggerStream(); -/* This stream is used throughout Loris (and may be used by clients) - to provide debugging information. Characters streamed onto debugger are - buffered until a newline is received, and then the entire contents - of the stream are flushed to the current debugger handler (stderr, - by default). - - debugger is enabled only when compiled with the preprocessor macro - Debug_Loris defined. It cannot be enabled using setDebuggerHandler() - if Debug_Loris is undefined. When Debug_Loris is not defined, - characters streamed onto debugger are never posted nor are they - otherwise accessible. - */ - -// for convenience, import endl and ends from std into Loris: -using std::endl; -using std::ends; - -} // end of namespace Loris - -#endif /* def __cplusplus */ - -/* - * handler assignment, c linkable: - */ - -#ifdef __cplusplus -// begin namespace -namespace Loris { -extern "C" { -#endif // def __cplusplus - -// These functions do not throw exceptions. -typedef void(*NotificationHandler)(const char * s); -NotificationHandler setNotifierHandler( NotificationHandler fn ); -/* Specify a new handling procedure for posting user feedback, and return - the current handler. - */ - -NotificationHandler setDebuggerHandler( NotificationHandler fn ); -/* Specify a new handling procedure for posting debugging information, and return - the current handler. This has no effect unless compiled with the Debug_Loris - preprocessor macro defined. - */ - -#ifdef __cplusplus -} // end extern "C" -} // end of namespace Loris -#endif // def __cplusplus - - -#endif /* ndef INCLUDE_NOTIFIER_H */ diff --git a/loris_library/Source/include/loris/Oscillator.h b/loris_library/Source/include/loris/Oscillator.h deleted file mode 100644 index 79631f4..0000000 --- a/loris_library/Source/include/loris/Oscillator.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef INCLUDE_OSCILLATOR_H -#define INCLUDE_OSCILLATOR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Oscillator.h - * - * Definition of class Loris::Oscillator, a Bandwidth-Enhanced Oscillator. - * - * Kelly Fitz, 31 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "NoiseGenerator.h" -#include "Filter.h" - -// begin namespace -namespace Loris { - -class Breakpoint; - -// --------------------------------------------------------------------------- -// class Oscillator -// -//! Class Oscillator represents the state of a single bandwidth-enhanced -//! sinusoidal oscillator used for synthesizing sounds from Reassigned -//! Bandwidth-Enhanced analysis data. Oscillator encapsulates the oscillator -//! state, including the instantaneous radian frequency (radians per -//! sample), amplitude, bandwidth coefficient, and phase, and a -//! bandlimited stochastic modulator. -//! -//! Class Synthesizer uses an instance of Oscillator to synthesize -//! bandwidth-enhanced Partials. -// -class Oscillator -{ -// --- implementation --- - - NoiseGenerator m_modulator; //! stochastic modulator - Filter m_filter; //! filter applied to the noise generator - - // instantaneous oscillator state: - double m_instfrequency; //! radians per sample - double m_instamplitude; //! absolute amplitude - double m_instbandwidth; //! bandwidth coefficient (noise energy / total energy) - - // accumulating phase state: - double m_determphase; //! deterministic phase in radians - -// --- interface --- -public: -// --- construction --- - - //! Construct a new Oscillator with all state parameters initialized to 0. - Oscillator( void ); - - // Copy, assignment, and destruction are free. - // - // Copied and assigned Oscillators have the duplicate state - // variables and the filters have the same coefficients, - // but the state of the filter delay lines is not copied. - -// --- oscillation --- - - //! Reset the instantaneous envelope parameters - //! (frequency, amplitude, bandwidth, and phase). - //! The sample rate is needed to convert the - //! Breakpoint frequency (Hz) to radians per sample. - void resetEnvelopes( const Breakpoint & bp, double srate ); - - //! Reset the phase of the Oscillator to the specified - //! value. This is done when the amplitude of a Partial - //! goes to zero, so that onsets are preserved in distilled - //! and collated Partials. - void setPhase( double ph ); - - //! Accumulate bandwidth-enhanced sinusoidal samples modulating the - //! oscillator state from its current values of radian frequency, amplitude, - //! and bandwidth to the specified target values. Accumulate samples into - //! the half-open (STL-style) range of doubles, starting at begin, and - //! ending before end (no sample is accumulated at end). The caller must - //! insure that the indices are valid. Target frequency and bandwidth are - //! checked to prevent aliasing and bogus bandwidth enhancement. - void oscillate( double * begin, double * end, - const Breakpoint & bp, double srate ); - -// --- accessors --- - - //! Return the instantaneous amplitde of the Oscillator. - double amplitude( void ) const { return m_instamplitude; } - - //! Return the instantaneous bandwidth of the Oscillator. - double bandwidth( void ) const { return m_instbandwidth; } - - //! Return the instantaneous phase of the Oscillator. - double phase( void ) const { return m_determphase; } - - //! Return the instantaneous radian frequency of the Oscillator. - double radianFreq( void ) const { return m_instfrequency; } - - //! Return access to the Filter used by this oscillator to - //! implement bandwidth-enhanced sinusoidal synthesis. - Filter & filter( void ) { return m_filter; } - -// --- static members --- - - //! Static local function for obtaining a prototype Filter - //! to use in Oscillator construction. Eventually, allow - //! external (client) specification of the Filter prototype. - static const Filter & prototype_filter( void ); - -}; // end of class Oscillator - -} // end of namespace Loris - -#endif /* ndef INCLUDE_OSCILLATOR_H */ diff --git a/loris_library/Source/include/loris/Partial.h b/loris_library/Source/include/loris/Partial.h deleted file mode 100644 index 1b26871..0000000 --- a/loris_library/Source/include/loris/Partial.h +++ /dev/null @@ -1,786 +0,0 @@ -#ifndef INCLUDE_PARTIAL_H -#define INCLUDE_PARTIAL_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Partial.h - * - * Definition of class Loris::Partial, and definitions and implementations of - * classes of const and non-const iterators over Partials, and the exception - * class InvalidPartial, thrown by some Partial members when invoked on a - * degenerate Partial having no Breakpoints. - * - * Kelly Fitz, 16 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Breakpoint.h" -#include "LorisExceptions.h" - -#include -//#include -//#include - -// begin namespace -namespace Loris { - -class Partial_Iterator; -class Partial_ConstIterator; - -// --------------------------------------------------------------------------- -// class Partial -// -//! An instance of class Partial represents a single component in the -//! reassigned bandwidth-enhanced additive model. A Partial consists of a -//! chain of Breakpoints describing the time-varying frequency, amplitude, -//! and bandwidth (or noisiness) envelopes of the component, and a 4-byte -//! label. The Breakpoints are non-uniformly distributed in time. For more -//! information about Reassigned Bandwidth-Enhanced Analysis and the -//! Reassigned Bandwidth-Enhanced Additive Sound Model, refer to the Loris -//! website: www.cerlsoundgroup.org/Loris/. -//! -//! The constituent time-tagged Breakpoints are accessible through -//! Partial:iterator and Partial::const_iterator interfaces. -//! These iterator classes implement the interface for bidirectional -//! iterators in the STL, including pre and post-increment and decrement, -//! and dereferencing. Dereferencing a Partial::itertator or -//! Partial::const_itertator yields a reference to a Breakpoint. Additionally, -//! these iterator classes have breakpoint() and time() members, returning -//! the Breakpoint (by reference) at the current iterator position and the -//! time (by value) corresponding to that Breakpoint. -//! -//! Partial is a leaf class, do not subclass. -//! -//! Most of the implementation of Partial delegates to a few -//! container-dependent members. The following members are -//! container-dependent, the other members are implemented in -//! terms of these: -//! default construction -//! copy (construction) -//! operator= (assign) -//! operator== (equivalence) -//! size -//! insert( pos, Breakpoint ) -//! erase( b, e ) -//! findAfter( time ) -//! begin (const and non-const) -//! end (const and non-const) -//! first (const and non-const) -//! last (const and non-const) -// -class Partial -{ -// -- public interface -- -public: - -// -- types -- - - //! underlying Breakpoint container type, used by - //! the iterator types defined below: - typedef std::map< double, Breakpoint > container_type; - - // typedef std::vector< std::pair< double, Breakpoint > > container_type; - // see Partial.C for a discussion of issues surrounding the - // choice of std::map as a Breakpoint container. - - //! 32 bit type for labeling Partials - typedef int label_type; - - //! non-const iterator over (time, Breakpoint) pairs in this Partial - typedef Partial_Iterator iterator; - - //! const iterator over (time, Breakpoint) pairs in this Partial - typedef Partial_ConstIterator const_iterator; - - //! size type for number of Breakpoints in this Partial - typedef container_type::size_type size_type; - -// -- construction -- - - //! Retun a new empty (no Breakpoints) Partial. - Partial( void ); - - //! Retun a new Partial from a half-open (const) iterator range - //! of time-Breakpoint pairs. - //! - //! \param beg is the beginning of the range of time-Breakpoint - //! pairs to insert into the new Partial. - //! \param end is the end of the range of time-Breakpoint pairs - //! to insert into the new Partial. - Partial( const_iterator beg, const_iterator end ); - - //! Return a new Partial that is an exact copy (has an identical set - //! of Breakpoints, at identical times, and the same label) of another - //! Partial. - //! - //! \param other is the Partial to copy. - Partial( const Partial & other ); - - //! Destroy this Partial. - ~Partial( void ); - -// -- assignment -- - - //! Make this Partial an exact copy (has an identical set of - //! Breakpoints, at identical times, and the same label) of another - //! Partial. - //! - //! \param other is the Partial to copy. - Partial & operator=( const Partial & other ); - -// -- container-dependent implementation -- - - //! Return an iterator refering to the position of the first - //! Breakpoint in this Partial's envelope, or end() if there - //! are no Breakpoints in the Partial. - iterator begin( void ); - - //! Return a const iterator refering to the position of the first - //! Breakpoint in this Partial's envelope, or end() if there - //! are no Breakpoints in the Partial. - const_iterator begin( void ) const; - - //! Return an iterator refering to the position past the last - //! Breakpoint in this Partial's envelope. The iterator returned by - //! end() (like the iterator returned by the end() member of any STL - //! container) does not refer to a valid Breakpoint. - iterator end( void ); - - //! Return a const iterator refering to the position past the last - //! Breakpoint in this Partial's envelope. The iterator returned by - //! end() (like the iterator returned by the end() member of any STL - //! container) does not refer to a valid Breakpoint. - const_iterator end( void ) const; - - //! Breakpoint removal: erase the Breakpoints in the specified range, - //! and return an iterator referring to the position after the, - //! erased range. - //! - //! \param beg is the beginning of the range of Breakpoints to erase - //! \param end is the end of the range of Breakpoints to erase - //! \return The position of the first Breakpoint after the range - //! of removed Breakpoints, or end() if the last Breakpoint - //! in the Partial was removed. - iterator erase( iterator beg, iterator end ); - - //! Return an iterator refering to the insertion position for a - //! Breakpoint at the specified time (that is, the position of the first - //! Breakpoint at a time later than the specified time). - //! - //! \param time is the time in seconds to find - //! \return The last position (iterator) at which a Breakpoint at the - //! specified time could be inserted (the position of the - //! first Breakpoint later than time). - iterator findAfter( double time ); - - //! Return a const iterator refering to the insertion position for a - //! Breakpoint at the specified time (that is, the position of the first - //! Breakpoint at a time later than the specified time). - //! - //! \param time is the time in seconds to find - //! \return The last position (iterator) at which a Breakpoint at the - //! specified time could be inserted (the position of the - //! first Breakpoint later than time). - const_iterator findAfter( double time ) const; - - //! Breakpoint insertion: insert a copy of the specified Breakpoint in the - //! parameter envelope at time (seconds), and return an iterator - //! refering to the position of the inserted Breakpoint. - //! - //! \param time is the time in seconds at which to insert the new - //! Breakpoint. - //! \param bp is the new Breakpoint to insert. - //! \return the position (iterator) of the newly-inserted - //! time-Breakpoint pair. - iterator insert( double time, const Breakpoint & bp ); - - //! Return the number of Breakpoints in this Partial. - //! - //! \return The number of Breakpoints in this Partial. - size_type size( void ) const; - -// -- access -- - - //! Return the duration (in seconds) spanned by the Breakpoints in - //! this Partial. Note that the synthesized onset time will differ, - //! depending on the fade time used to synthesize this Partial (see - //! class Synthesizer). - double duration( void ) const; - - //! Return the time (in seconds) of the last Breakpoint in this - //! Partial. Note that the synthesized onset time will differ, - //! depending on the fade time used to synthesize this Partial (see - //! class Synthesizer). - double endTime( void ) const; - - //! Return a reference to the first Breakpoint in the Partial's - //! envelope. - //! - //! \throw InvalidPartial if there are no Breakpoints. - Breakpoint & first( void ); - - //! Return a const reference to the first Breakpoint in the Partial's - //! envelope. - //! - //! \throw InvalidPartial if there are no Breakpoints. - const Breakpoint & first( void ) const; - - //! Return the phase (in radians) of this Partial at its start time - //! (the phase of the first Breakpoint). Note that the initial - //! synthesized phase will differ, depending on the fade time used - //! to synthesize this Partial (see class Synthesizer). - double initialPhase( void ) const; - - //! Return the 32-bit label for this Partial as an integer. - label_type label( void ) const; - - //! Return a reference to the last Breakpoint in the Partial's - //! envelope. - //! - //! \throw InvalidPartial if there are no Breakpoints. - Breakpoint & last( void ); - - //! Return a const reference to the last Breakpoint in the Partial's - //! envelope. - //! - //! \throw InvalidPartial if there are no Breakpoints. - const Breakpoint & last( void ) const; - - //! Same as size(). Return the number of Breakpoints in this Partial. - size_type numBreakpoints( void ) const; - - //! Return the time (in seconds) of the first Breakpoint in this - //! Partial. Note that the synthesized onset time will differ, - //! depending on the fade time used to synthesize this Partial (see - //! class Synthesizer). - double startTime( void ) const; - -// -- mutation -- - - //! Absorb another Partial's energy as noise (bandwidth), - //! by accumulating the other's energy as noise energy - //! in the portion of this Partial's envelope that overlaps - //! (in time) with the other Partial's envelope. - //! - //! \param other is the Partial to absorb. - void absorb( const Partial & other ); - - //! Set the label for this Partial to the specified 32-bit value. - void setLabel( label_type l ); - - //! Remove the Breakpoint at the position of the given - //! iterator, invalidating the iterator. Return a - //! iterator referring to the next valid position, or to - //! the end of the Partial if the last Breakpoint is removed. - //! - //! \param pos is the position of the time-Breakpoint pair - //! to be removed. - //! \return The position (iterator) of the time-Breakpoint - //! pair after the one that was removed. - //! \post The iterator pos is invalid. - iterator erase( iterator pos ); - - //! Return an iterator refering to the position of the - //! Breakpoint in this Partial nearest the specified time. - //! - //! \param time is the time to find. - //! \return The position (iterator) of the time-Breakpoint - //! pair nearest (in time) to the specified time. - iterator findNearest( double time ); - - //! Return a const iterator refering to the position of the - //! Breakpoint in this Partial nearest the specified time. - //! - //! \param time is the time to find. - //! \return The position (iterator) of the time-Breakpoint - //! pair nearest (in time) to the specified time. - const_iterator findNearest( double time ) const; - - //! Break this Partial at the specified position (iterator). - //! The Breakpoint at the specified position becomes the first - //! Breakpoint in a new Partial. Breakpoints at the specified - //! position and subsequent positions are removed from this - //! Partial and added to the new Partial, which is returned. - //! - //! \param pos is the position at which to split this Partial. - //! \return A new Partial consisting of time-Breakpoint pairs - //! beginning with pos and extending to the end of this - //! Partial. - //! \post All positions beginning with pos and extending to - //! the end of this Partial have been removed. - Partial split( iterator pos ); - -// -- parameter interpolation/extrapolation -- - - //! Define the default fade time for computing amplitude at the ends - //! of a Partial. Floating point round-off errors make fadeTime == 0.0 - //! dangerous and unpredictable. 1 ns is short enough to prevent rounding - //! errors in the least significant bit of a 48-bit mantissa for times - //! up to ten hours. - //! - //! 1 nanosecond, see Partial.C - static const double ShortestSafeFadeTime; - - //! Return the interpolated amplitude of this Partial at the - //! specified time. If non-zero fadeTime is specified, - //! then the amplitude at the ends of the Partial is computed using - //! a linear fade. The default fadeTime is ShortestSafeFadeTime, - //! see the definition of ShortestSafeFadeTime, above. - //! - //! \param time is the time in seconds at which to evaluate the - //! Partial. - //! \param fadeTime is the duration in seconds over which Partial - //! amplitudes fade at the ends. The default value is - //! ShortestSafeFadeTime, 1 ns. - //! \return The amplitude of this Partial at the specified time. - //! \pre The Partial must have at least one Breakpoint. - //! \throw InvalidPartial if the Partial has no Breakpoints. - double amplitudeAt( double time, double fadeTime = ShortestSafeFadeTime ) const; - - //! Return the interpolated bandwidth (noisiness) coefficient of - //! this Partial at the specified time. At times beyond the ends of - //! the Partial, return the bandwidth coefficient at the nearest - //! envelope endpoint. - //! - //! \param time is the time in seconds at which to evaluate the - //! Partial. - //! \return The bandwidth of this Partial at the specified time. - //! \pre The Partial must have at least one Breakpoint. - //! \throw InvalidPartial if the Partial has no Breakpoints. - double bandwidthAt( double time ) const; - - //! Return the interpolated frequency (in Hz) of this Partial at the - //! specified time. At times beyond the ends of the Partial, return - //! the frequency at the nearest envelope endpoint. - //! - //! \param time is the time in seconds at which to evaluate the - //! Partial. - //! \return The frequency of this Partial at the specified time. - //! \pre The Partial must have at least one Breakpoint. - //! \throw InvalidPartial if the Partial has no Breakpoints. - double frequencyAt( double time ) const; - - //! Return the interpolated phase (in radians) of this Partial at - //! the specified time. At times beyond the ends of the Partial, - //! return the extrapolated from the nearest envelope endpoint - //! (assuming constant frequency, as reported by frequencyAt()). - //! - //! \param time is the time in seconds at which to evaluate the - //! Partial. - //! \return The phase of this Partial at the specified time. - //! \pre The Partial must have at least one Breakpoint. - //! \throw InvalidPartial if the Partial has no Breakpoints. - double phaseAt( double time ) const; - - //! Return the interpolated parameters of this Partial at - //! the specified time, same as building a Breakpoint from - //! the results of frequencyAt, ampitudeAt, bandwidthAt, and - //! phaseAt, but performs only one Breakpoint envelope search. - //! If non-zero fadeTime is specified, then the - //! amplitude at the ends of the Partial is coomputed using a - //! linear fade. The default fadeTime is ShortestSafeFadeTime. - //! - //! \param time is the time in seconds at which to evaluate the - //! Partial. - //! \param fadeTime is the duration in seconds over which Partial - //! amplitudes fade at the ends. The default value is - //! ShortestSafeFadeTime, 1 ns. - //! \return A Breakpoint describing the parameters of this Partial - //! at the specified time. - //! \pre The Partial must have at least one Breakpoint. - //! \throw InvalidPartial if the Partial has no Breakpoints. - Breakpoint parametersAt( double time, double fadeTime = ShortestSafeFadeTime ) const; - -// -- implementation -- -private: - - label_type _label; - container_type _breakpoints; // Breakpoint envelope - -}; // end of class Partial - -// --------------------------------------------------------------------------- -// class Partial_Iterator -// -//! Non-const iterator for the Loris::Partial Breakpoint map. Wraps -//! the non-const iterator for the (time,Breakpoint) pair container -//! Partial::container_type. Partial_Iterator implements a -//! bidirectional iterator interface, and additionally offers time -//! and Breakpoint (reference) access through time() and breakpoint() -//! members. -// -class Partial_Iterator -{ -// -- instance variables -- - - typedef Partial::container_type BaseContainer; - typedef BaseContainer::iterator BaseIterator; - BaseIterator _iter; - -// -- public interface -- -public: -// -- bidirectional iterator interface -- - - //! The iterator category, for copmpatibility with - //! C++ standard library algorithms - typedef BaseIterator::iterator_category iterator_category; - - //! The type of element that can be accessed through this - //! iterator (Breakpoint). - typedef Breakpoint value_type; - - //! The type representing the distance between two of these - //! iterators. - typedef BaseIterator::difference_type difference_type; - - //! The type of a pointer to the type of element that can - //! be accessed through this iterator (Breakpoint *). - typedef Breakpoint * pointer; - - //! The type of a reference to the type of element that can - //! be accessed through this iterator (Breakpoint &). - typedef Breakpoint & reference; - -// construction: - - //! Construct a new iterator referring to no position in - //! any Partial. - Partial_Iterator( void ) {} - - // (allow compiler to generate copy, assignment, and destruction) - -// pre-increment/decrement: - - //! Pre-increment operator - advance the position of the iterator - //! and return the iterator itself. - //! - //! \return This iterator (reference to self). - //! \pre The iterator must be a valid position before the end - //! in some Partial. - Partial_Iterator& operator ++ () { ++_iter; return *this; } - - //! Pre-decrement operator - move the position of the iterator - //! back by one and return the iterator itself. - //! - //! \return This iterator (reference to self). - //! \pre The iterator must be a valid position after the beginning - //! in some Partial. - Partial_Iterator& operator -- () { --_iter; return *this; } - -// post-increment/decrement: - - //! Post-increment operator - advance the position of the iterator - //! and return a copy of the iterator before it was advanced. - //! The int argument is unused compiler magic. - //! - //! \return An iterator that is a copy of this iterator before - //! being advanced. - //! \pre The iterator must be a valid position before the end - //! in some Partial. - Partial_Iterator operator ++ ( int ) { return Partial_Iterator( _iter++ ); } - - //! Post-decrement operator - move the position of the iterator - //! back by one and return a copy of the iterator before it was - //! decremented. The int argument is unused compiler magic. - //! - //! \return An iterator that is a copy of this iterator before - //! being decremented. - //! \pre The iterator must be a valid position after the beginning - //! in some Partial. - Partial_Iterator operator -- ( int ) { return Partial_Iterator( _iter-- ); } - -// dereference (for treating Partial like a -// STL collection of Breakpoints): - - //! Dereference operator. - //! - //! \return A reference to the Breakpoint at the position of this - //! iterator. - Breakpoint & operator * ( void ) const { return breakpoint(); } - - - //! Dereference operator. - //! - //! \return A reference to the Breakpoint at the position of this - //! iterator. - //Breakpoint & operator * ( void ) { return breakpoint(); } - - //! Pointer operator. - //! - //! \return A pointer to the Breakpoint at the position of this - //! iterator. - Breakpoint * operator -> ( void ) const { return & breakpoint(); } - - //! Pointer operator. - //! - //! \return A pointer to the Breakpoint at the position of this - //! iterator. - //Breakpoint * operator -> ( void ) { return & breakpoint(); } - -// comparison: - - //! Equality comparison operator. - //! - //! \param lhs the iterator on the left side of the operator. - //! \param rhs the iterator on the right side of the operator. - //! \return true if the two iterators refer to the same position - //! in the same Partial, false otherwise. - friend bool operator == ( const Partial_Iterator & lhs, - const Partial_Iterator & rhs ) - { return lhs._iter == rhs._iter; } - - //! Inequality comparison operator. - //! - //! \param lhs the iterator on the left side of the operator. - //! \param rhs the iterator on the right side of the operator. - //! \return false if the two iterators refer to the same position - //! in the same Partial, true otherwise. - friend bool operator != ( const Partial_Iterator & lhs, - const Partial_Iterator & rhs ) - { return lhs._iter != rhs._iter; } - -// -- time and Breakpoint access -- - - //! Breakpoint accessor. - //! - //! \return A const reference to the Breakpoint at the position of this - //! iterator. - Breakpoint & breakpoint( void ) const - { return _iter->second; } - - //! Breakpoint accessor. - //! - //! \return A reference to the Breakpoint at the position of this - //! iterator. - //Breakpoint & breakpoint( void ) - // { return _iter->second; } - - //! Time accessor. - //! - //! \return The time in seconds of the Breakpoint at the position - //! of this iterator. - double time( void ) const - { return _iter->first; } - -// -- BaseIterator conversions -- -private: - // construction by GenericBreakpointContainer from a BaseIterator: - Partial_Iterator( const BaseIterator & it ) : - _iter(it) {} - - friend class Partial; - - // befriend Partial_ConstIterator, - // for const construction from non-const: - friend class Partial_ConstIterator; - -}; // end of class Partial_Iterator - -// --------------------------------------------------------------------------- -// class Partial_ConstIterator -// -//! Const iterator for the Loris::Partial Breakpoint map. Wraps -//! the non-const iterator for the (time,Breakpoint) pair container -//! Partial::container_type. Partial_Iterator implements a -//! bidirectional iterator interface, and additionally offers time -//! and Breakpoint (reference) access through time() and breakpoint() -//! members. -// -class Partial_ConstIterator -{ -// -- instance variables -- - typedef Partial::container_type BaseContainer; - typedef BaseContainer::const_iterator BaseIterator; - BaseIterator _iter; - -// -- public interface -- -public: -// -- bidirectional iterator interface -- - - //! The iterator category, for copmpatibility with - //! C++ standard library algorithms - typedef BaseIterator::iterator_category iterator_category; - - //! The type of element that can be accessed through this - //! iterator (Breakpoint). - typedef Breakpoint value_type; - - //! The type representing the distance between two of these - //! iterators. - typedef BaseIterator::difference_type difference_type; - - //! The type of a pointer to the type of element that can - //! be accessed through this iterator (const Breakpoint *). - typedef const Breakpoint * pointer; - - //! The type of a reference to the type of element that can - //! be accessed through this iterator (const Breakpoint &). - typedef const Breakpoint & reference; - -// construction: - - //! Construct a new iterator referring to no position in - //! any Partial. - Partial_ConstIterator( void ) {} - - //! Construct a new const iterator from a non-const iterator. - //! - //! \param other a non-const iterator from which to make - //! a read-only copy. - Partial_ConstIterator( const Partial_Iterator & other ) : - _iter( other._iter ) {} - - // (allow compiler to generate copy, assignment, and destruction): - -// pre-increment/decrement: - - //! Pre-increment operator - advance the position of the iterator - //! and return the iterator itself. - //! - //! \return This iterator (reference to self). - //! \pre The iterator must be a valid position before the end - //! in some Partial. - Partial_ConstIterator& operator ++ () { ++_iter; return *this; } - - //! Pre-decrement operator - move the position of the iterator - //! back by one and return the iterator itself. - //! - //! \return This iterator (reference to self). - //! \pre The iterator must be a valid position after the beginning - //! in some Partial. - Partial_ConstIterator& operator -- () { --_iter; return *this; } - -// post-increment/decrement: - - //! Post-increment operator - advance the position of the iterator - //! and return a copy of the iterator before it was advanced. - //! The int argument is unused compiler magic. - //! - //! \return An iterator that is a copy of this iterator before - //! being advanced. - //! \pre The iterator must be a valid position before the end - //! in some Partial. - Partial_ConstIterator operator ++ ( int ) { return Partial_ConstIterator( _iter++ ); } - - //! Post-decrement operator - move the position of the iterator - //! back by one and return a copy of the iterator before it was - //! decremented. The int argument is unused compiler magic. - //! - //! \return An iterator that is a copy of this iterator before - //! being decremented. - //! \pre The iterator must be a valid position after the beginning - //! in some Partial. - Partial_ConstIterator operator -- ( int ) { return Partial_ConstIterator( _iter-- ); } - -// dereference (for treating Partial like a -// STL collection of Breakpoints): - - //! Dereference operator. - //! - //! \return A const reference to the Breakpoint at the position of this - //! iterator. - const Breakpoint & operator * ( void ) const { return breakpoint(); } - - //! Pointer operator. - //! - //! \return A const pointer to the Breakpoint at the position of this - //! iterator. - const Breakpoint * operator -> ( void ) const { return & breakpoint(); } - -// comparison: - - //! Equality comparison operator. - //! - //! \param lhs the iterator on the left side of the operator. - //! \param rhs the iterator on the right side of the operator. - //! \return true if the two iterators refer to the same position - //! in the same Partial, false otherwise. - friend bool operator == ( const Partial_ConstIterator & lhs, - const Partial_ConstIterator & rhs ) - { return lhs._iter == rhs._iter; } - - //! Inequality comparison operator. - //! - //! \param lhs the iterator on the left side of the operator. - //! \param rhs the iterator on the right side of the operator. - //! \return false if the two iterators refer to the same position - //! in the same Partial, true otherwise. - friend bool operator != ( const Partial_ConstIterator & lhs, - const Partial_ConstIterator & rhs ) - { return lhs._iter != rhs._iter; } - -// -- time and Breakpoint access -- - - //! Breakpoint accessor. - //! - //! \return A const reference to the Breakpoint at the position of this - //! iterator. - const Breakpoint & breakpoint( void ) const - { return _iter->second; } - - //! Time accessor. - //! - //! \return The time in seconds of the Breakpoint at the position - //! of this iterator. - double time( void ) const - { return _iter->first; } - -// -- BaseIterator conversions -- -private: - // construction by GenericBreakpointContainer from a BaseIterator: - Partial_ConstIterator( BaseIterator it ) : - _iter(it) {} - - friend class Partial; - -}; // end of class Partial_ConstIterator - -// --------------------------------------------------------------------------- -// class InvalidPartial -// -//! Class of exceptions thrown when a Partial is found to be badly configured -//! or otherwise invalid. -// -class InvalidPartial : public InvalidObject -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically byt he Throw macro). - InvalidPartial( const std::string & str, const std::string & where = "" ) : - InvalidObject( std::string("Invalid Partial -- ").append( str ), where ) {} - -}; // end of class InvalidPartial - -} // end of namespace Loris - -#endif /* ndef INCLUDE_PARTIAL_H */ diff --git a/loris_library/Source/include/loris/PartialBuilder.h b/loris_library/Source/include/loris/PartialBuilder.h deleted file mode 100644 index 2592ffc..0000000 --- a/loris_library/Source/include/loris/PartialBuilder.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef INCLUDE_PARTIALBUILDER_H -#define INCLUDE_PARTIALBUILDER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PartialBuilder.h - * - * Implementation of a class representing a policy for connecting peaks - * extracted from a reassigned time-frequency spectrum to form ridges - * and construct Partials. - * - * This strategy attemps to follow a reference frequency envelope when - * forming Partials, by prewarping all peak frequencies according to the - * (inverse of) frequency reference envelope. At the end of the analysis, - * Partial frequencies need to be un-warped by calling fixPartialFrequencies(). - * - * Kelly Fitz, 28 May 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Partial.h" -#include "PartialList.h" -#include "PartialPtrs.h" -#include "SpectralPeaks.h" - -#include - -// begin namespace -namespace Loris { - -class Envelope; - -// --------------------------------------------------------------------------- -// class PartialBuilder -// -// A class representing the process of connecting peaks (ridges) on a -// reassigned time-frequency surface to form Partials. -// -class PartialBuilder -{ -// --- public interface --- - -public: - - // constructor - // - // Construct a new builder that constrains Partial frequnecy - // drift by the specified drift value in Hz. - PartialBuilder( double drift ); - - // constructor - // - // Construct a new builder that constrains Partial frequnecy - // drift by the specified drift value in Hz. The frequency - // warping envelope is applied to the spectral peak frequencies - // and the frequency drift parameter in each frame before peaks - // are linked to eligible Partials. All the Partial frequencies - // need to be un-warped at the ned of the building process, by - // calling finishBuilding(). - PartialBuilder( double drift, const Envelope & freqWarpEnv ); - - // buildPartials - // - // Append spectral peaks, extracted from a reassigned time-frequency - // spectrum, to eligible Partials, where possible. Peaks that cannot - // be used to extend eliglble Partials spawn new Partials. - // - // This is similar to the basic MQ partial formation strategy, except that - // before matching, all frequencies are normalized by the value of the - // warping envelope at the time of the current frame. This means that - // the frequency envelopes of all the Partials are warped, and need to - // be un-normalized by calling finishBuilding at the end of the building - // process. - void buildPartials( Peaks & peaks, double frameTime ); - - // finishBuilding - // - // Un-do the frequency warping performed in buildPartials, and return - // the Partials that were built. After calling finishBuilding, the - // builder is returned to its initial state, and ready to build another - // set of Partials. Partials are returned by appending them to the - // supplied PartialList. - void finishBuilding( PartialList & product ); - -private: - -// --- auxiliary member functions --- - - double freq_distance( const Partial & partial, const SpectralPeak & pk ); - - bool better_match( const Partial & part, const SpectralPeak & pk1, - const SpectralPeak & pk2 ); - bool better_match( const Partial & part1, - const Partial & part2, const SpectralPeak & pk ); - - -// --- collected partials --- - - PartialList mCollectedPartials; // collect partials here - -// --- builder state variables --- - - PartialPtrs mEligiblePartials; - PartialPtrs mNewlyEligible; // keep track of eligible partials here - -// --- parameters --- - - std::auto_ptr< Envelope > mFreqWarping; // reference envelope - - double mFreqDrift; - -// --- disallow copy and assignment --- - - PartialBuilder( const PartialBuilder & ); - PartialBuilder& operator=( const PartialBuilder & ); - -}; // end of class PartialBuilder - -} // end of namespace Loris - -#endif /* ndef INCLUDE_PARTIALBUILDER_H */ diff --git a/loris_library/Source/include/loris/PartialList.h b/loris_library/Source/include/loris/PartialList.h deleted file mode 100644 index ca91509..0000000 --- a/loris_library/Source/include/loris/PartialList.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef INCLUDE_PARTIALLIST_H -#define INCLUDE_PARTIALLIST_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PartialList.h - * - * Type definition of Loris::PartialList, which is just a name - * for std::list< Loris::Partial >. - * - * Kelly Fitz, 6 March 2002 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -// Seems like we shouldn't need to include Partial.h, but -// without it, I can't instantiate a PartialList. I need -// a definition of Partial for PartialList to be unambiguous. -#include "Partial.h" -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class PartialList -// -// PartialList is a typedef for a std::list<> of Loris Partials. The -// oscciated bidirectional iterators are also defined as -// PartialListIterator and PartialListConstIterator. Since these are -// simply typedefs, they classes have identical interfaces to std::list, -// std::list::iterator, and std::list::const_iterator, respectively. -// -typedef std::list< Loris::Partial > PartialList; -typedef std::list< Loris::Partial >::iterator PartialListIterator; -typedef std::list< Loris::Partial >::const_iterator PartialListConstIterator; - -} // end of namespace Loris - -#endif /* ndef INCLUDE_PARTIALLIST_H */ diff --git a/loris_library/Source/include/loris/PartialPtrs.h b/loris_library/Source/include/loris/PartialPtrs.h deleted file mode 100644 index a773aec..0000000 --- a/loris_library/Source/include/loris/PartialPtrs.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef INCLUDE_PARTIALPTRS_H -#define INCLUDE_PARTIALPTRS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PartialPtrs.h - * - * Type definition of Loris::PartialPtrs. - * - * PartialPtrs is a collection of pointers to Partials that - * can be used (among other things) for algorithms that operate - * on a range of Partials, but don't rely on access to their - * container. - * - * Kelly Fitz, 23 May 2002 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Partial.h" -#include -#include - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// class PartialPtrs -// -// PartialPtrs is a typedef for a std::vectror<> of pointers to Loris -// Partials. The oscciated bidirectional iterators are also defined as -// PartialPtrsIterator and PartialPtrsConstIterator. Since these are -// simply typedefs, they classes have identical interfaces to -// std::vector, std::vector::iterator, and std::vector::const_iterator, -// respectively. -// -// PartialPtrs is a collection of pointers to Partials that can be used -// (among other things) for algorithms that operate on a range of -// Partials, but don't rely on access to their container. A template -// function defined in a header file can convert a range of Partials to a -// PartialPtrs using the template free function fillPartialPtrs() (see -// below), and pass the latter to the algorithm implementation, thereby -// generalizing access to the algorithm across containers without -// exposing the implementation in the header file. -// -typedef std::vector< Partial * > PartialPtrs; -typedef std::vector< Partial * >::iterator PartialPtrsIterator; -typedef std::vector< Partial * >::const_iterator PartialPtrsConstIterator; - -typedef std::vector< const Partial * > ConstPartialPtrs; -typedef std::vector< const Partial * >::iterator ConstPartialPtrsIterator; -typedef std::vector< const Partial * >::const_iterator ConstPartialPtrsConstIterator; - - -// --------------------------------------------------------------------------- -// fillPartialPtrs -// --------------------------------------------------------------------------- -// Fill the specified PartialPtrs with pointers to the Partials n the -// specified half-open (STL-style) range. This is a generally useful -// operation that can be used to adapt algorithms to work with arbitrary -// containers of Partials without exposing the algorithms themselves in -// the header files. -// -template -void fillPartialPtrs( Iter begin, Iter end, PartialPtrs & fillme ) -{ - fillme.reserve( std::distance( begin, end ) ); - fillme.clear(); - while ( begin != end ) - fillme.push_back( &(*begin++) ); -} - -template -void fillPartialPtrs( Iter begin, Iter end, ConstPartialPtrs & fillme ) -{ - fillme.reserve( std::distance( begin, end ) ); - fillme.clear(); - while ( begin != end ) - fillme.push_back( &(*begin++) ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_PARTIALPTRS_H */ diff --git a/loris_library/Source/include/loris/PartialUtils.h b/loris_library/Source/include/loris/PartialUtils.h deleted file mode 100644 index 4dc4c74..0000000 --- a/loris_library/Source/include/loris/PartialUtils.h +++ /dev/null @@ -1,1190 +0,0 @@ -#ifndef INCLUDE_PARTIALUTILS_H -#define INCLUDE_PARTIALUTILS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PartialUtils.h - * - * A group of Partial utility function objects for use with STL - * searching and sorting algorithms. PartialUtils is a namespace - * within the Loris namespace. - * - * This file defines three kinds of functors: - * - Partial mutators - * - predicates on Partials - * - Partial comparitors - * - * Kelly Fitz, 6 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Envelope.h" -#include "Partial.h" - -#include -#include -#include - -// begin namespace -namespace Loris { - -namespace PartialUtils { - -// -- Partial mutating functors -- - -// --------------------------------------------------------------------------- -// PartialMutator -// -//! PartialMutator is an abstract base class for Partial mutators, -//! functors that operate on Partials according to a time-varying -//! envelope. The base class manages a polymorphic Envelope instance -//! that provides the time-varying mutation parameters. -//! -//! \invariant env is a non-zero pointer to a valid instance of a -//! class derived from the abstract class Envelope. -class PartialMutator : public std::unary_function< Partial, void > -{ -public: - - //! Construct a new PartialMutator from a constant mutation factor. - PartialMutator( double x ); - - //! Construct a new PartialMutator from an Envelope representing - //! a time-varying mutation factor. - PartialMutator( const Envelope & e ); - - //! Construct a new PartialMutator that is a copy of another. - PartialMutator( const PartialMutator & rhs ); - - //! Destroy this PartialMutator, deleting its Envelope. - virtual ~PartialMutator( void ); - - //! Make this PartialMutator a duplicate of another one. - //! - //! \param rhs is the PartialMutator to copy. - PartialMutator & operator=( const PartialMutator & rhs ); - - //! Function call operator: apply a mutation factor to the - //! specified Partial. Derived classes must implement this - //! member. - virtual void operator()( Partial & p ) const = 0; - -protected: - - //! pointer to an envelope that governs the - //! time-varying mutation - Envelope * env; -}; - -// --------------------------------------------------------------------------- -// AmplitudeScaler -// -//! Scale the amplitude of the specified Partial according to -//! an envelope representing a time-varying amplitude scale value. -// -class AmplitudeScaler : public PartialMutator -{ -public: - - //! Construct a new AmplitudeScaler from a constant scale factor. - AmplitudeScaler( double x ) : PartialMutator( x ) {} - - //! Construct a new AmplitudeScaler from an Envelope representing - //! a time-varying scale factor. - AmplitudeScaler( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: apply a scale factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// scaleAmplitude -// --------------------------------------------------------------------------- -//! Scale the amplitude of the specified Partial according to -//! an envelope representing a amplitude scale value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Arg > -void scaleAmplitude( Partial & p, const Arg & arg ) -{ - AmplitudeScaler scaler( arg ); - scaler( p ); -} - -// --------------------------------------------------------------------------- -// scaleAmplitude -// --------------------------------------------------------------------------- -//! Scale the amplitude of a sequence of Partials according to -//! an envelope representing a amplitude scale value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Iter, class Arg > -void scaleAmplitude( Iter b, Iter e, const Arg & arg ) -{ - AmplitudeScaler scaler( arg ); - while ( b != e ) - { - scaler( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// BandwidthScaler -// -//! Scale the bandwidth of the specified Partial according to -//! an envelope representing a time-varying bandwidth scale value. -// -class BandwidthScaler : public PartialMutator -{ -public: - - //! Construct a new BandwidthScaler from a constant scale factor. - BandwidthScaler( double x ) : PartialMutator( x ) {} - - //! Construct a new BandwidthScaler from an Envelope representing - //! a time-varying scale factor. - BandwidthScaler( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: apply a scale factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// scaleBandwidth -// --------------------------------------------------------------------------- -//! Scale the bandwidth of the specified Partial according to -//! an envelope representing a amplitude scale value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Arg > -void scaleBandwidth( Partial & p, const Arg & arg ) -{ - BandwidthScaler scaler( arg ); - scaler( p ); -} - -// --------------------------------------------------------------------------- -// scaleBandwidth -// --------------------------------------------------------------------------- -//! Scale the bandwidth of a sequence of Partials according to -//! an envelope representing a bandwidth scale value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Iter, class Arg > -void scaleBandwidth( Iter b, Iter e, const Arg & arg ) -{ - BandwidthScaler scaler( arg ); - while ( b != e ) - { - scaler( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// BandwidthSetter -// -//! Set the bandwidth of the specified Partial according to -//! an envelope representing a time-varying bandwidth value. -// -class BandwidthSetter : public PartialMutator -{ -public: - - //! Construct a new BandwidthSetter from a constant bw factor. - BandwidthSetter( double x ) : PartialMutator( x ) {} - - //! Construct a new BandwidthSetter from an Envelope representing - //! a time-varying bw factor. - BandwidthSetter( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: assign a bw factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// setBandwidth -// --------------------------------------------------------------------------- -//! Set the bandwidth of the specified Partial according to -//! an envelope representing a amplitude scale value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying bw factor. -// -template< class Arg > -void setBandwidth( Partial & p, const Arg & arg ) -{ - BandwidthSetter setter( arg ); - setter( p ); -} - -// --------------------------------------------------------------------------- -// setBandwidth -// --------------------------------------------------------------------------- -//! Set the bandwidth of a sequence of Partials according to -//! an envelope representing a bandwidth value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Iter, class Arg > -void setBandwidth( Iter b, Iter e, const Arg & arg ) -{ - BandwidthSetter setter( arg ); - while ( b != e ) - { - setter( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// FrequencyScaler -// -//! Scale the frequency of the specified Partial according to -//! an envelope representing a time-varying bandwidth scale value. -// -class FrequencyScaler : public PartialMutator -{ -public: - - //! Construct a new FrequencyScaler from a constant scale factor. - FrequencyScaler( double x ) : PartialMutator( x ) {} - - //! Construct a new FrequencyScaler from an Envelope representing - //! a time-varying scale factor. - FrequencyScaler( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: apply a scale factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// scaleFrequency -// --------------------------------------------------------------------------- -//! Scale the frequency of the specified Partial according to -//! an envelope representing a frequency scale value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Arg > -void scaleFrequency( Partial & p, const Arg & arg ) -{ - FrequencyScaler scaler( arg ); - scaler( p ); -} - -// --------------------------------------------------------------------------- -// scaleFrequency -// --------------------------------------------------------------------------- -//! Scale the frequency of a sequence of Partials according to -//! an envelope representing a frequency scale value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Iter, class Arg > -void scaleFrequency( Iter b, Iter e, const Arg & arg ) -{ - FrequencyScaler scaler( arg ); - while ( b != e ) - { - scaler( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// NoiseRatioScaler -// -//! Scale the relative noise content of the specified Partial according -//! to an envelope representing a time-varying bandwidth scale value. -// -class NoiseRatioScaler : public PartialMutator -{ -public: - - //! Construct a new NoiseRatioScaler from a constant scale factor. - NoiseRatioScaler( double x ) : PartialMutator( x ) {} - - //! Construct a new NoiseRatioScaler from an Envelope representing - //! a time-varying scale factor. - NoiseRatioScaler( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: apply a scale factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// scaleNoiseRatio -// --------------------------------------------------------------------------- -//! Scale the relative noise content of the specified Partial according to -//! an envelope representing a scale value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Arg > -void scaleNoiseRatio( Partial & p, const Arg & arg ) -{ - NoiseRatioScaler scaler( arg ); - scaler( p ); -} - -// --------------------------------------------------------------------------- -// scaleNoiseRatio -// --------------------------------------------------------------------------- -//! Scale the relative noise content of a sequence of Partials according to -//! an envelope representing a scale value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Iter, class Arg > -void scaleNoiseRatio( Iter b, Iter e, const Arg & arg ) -{ - NoiseRatioScaler scaler( arg ); - while ( b != e ) - { - scaler( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// PitchShifter -// -//! Shift the pitch of the specified Partial according to -//! the given pitch envelope. The pitch envelope is assumed to have -//! units of cents (1/100 of a halfstep). -// -class PitchShifter : public PartialMutator -{ -public: - - //! Construct a new PitchShifter from a constant scale factor. - PitchShifter( double x ) : PartialMutator( x ) {} - - //! Construct a new PitchShifter from an Envelope representing - //! a time-varying scale factor. - PitchShifter( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: apply a scale factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// shiftPitch -// --------------------------------------------------------------------------- -//! Shift the pitch of the specified Partial according to -//! an envelope representing a pitch value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant pitch factor or an Envelope -//! describing the time-varying pitch factor in cents (1/100 of a -//! halfstep). -// -template< class Arg > -void shiftPitch( Partial & p, const Arg & arg ) -{ - PitchShifter shifter( arg ); - shifter( p ); -} - -// --------------------------------------------------------------------------- -// shiftPitch -// --------------------------------------------------------------------------- -//! Shift the pitch of a sequence of Partials according to -//! an envelope representing a pitch value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant pitch factor or an Envelope -//! describing the time-varying pitch factor in cents (1/100 of a -//! halfstep). -// -template< class Iter, class Arg > -void shiftPitch( Iter b, Iter e, const Arg & arg ) -{ - PitchShifter shifter( arg ); - while ( b != e ) - { - shifter( *b++ ); - } -} - -// These ones are not derived from PartialMutator, because -// they don't use an Envelope and cannot be time-varying. - -// --------------------------------------------------------------------------- -// Cropper -// -//! Trim a Partial by removing Breakpoints outside a specified time span. -//! Insert a Breakpoint at the boundary when cropping occurs. -class Cropper -{ -public: - - //! Construct a new Cropper from a pair of times (in seconds) - //! representing the span of time to which Partials should be - //! cropped. - Cropper( double t1, double t2 ) : - minTime( std::min( t1, t2 ) ), - maxTime( std::max( t1, t2 ) ) - { - } - - //! Function call operator: crop the specified Partial. - //! Trim a Partial by removing Breakpoints outside the span offset - //! [minTime, maxTime]. Insert a Breakpoint at the boundary when - //! cropping occurs. - void operator()( Partial & p ) const; - -private: - double minTime, maxTime; -}; - -// --------------------------------------------------------------------------- -// crop -// --------------------------------------------------------------------------- -//! Trim a Partial by removing Breakpoints outside a specified time span. -//! Insert a Breakpoint at the boundary when cropping occurs. -//! -//! This operation may leave the Partial empty, if it previously had -//! no Breakpoints in the span [t1,t2]. -//! -//! \param p is the Partial to crop. -//! \param t1 is the beginning of the time span to which the Partial -//! should be cropped. -//! \param t2 is the end of the time span to which the Partial -//! should be cropped. -// -inline -void crop( Partial & p, double t1, double t2 ) -{ - Cropper cropper( t1, t2 ); - cropper( p ); -} - -// --------------------------------------------------------------------------- -// crop -// --------------------------------------------------------------------------- -//! Trim a sequence of Partials by removing Breakpoints outside a specified -//! time span. Insert a Breakpoint at the boundary when cropping occurs. -//! -//! This operation may leave some empty Partials, if they previously had -//! no Breakpoints in the span [t1,t2]. -//! -//! \param b is the beginning of a sequence of Partials to crop. -//! \param e is the end of a sequence of Partials to crop. -//! \param t1 is the beginning of the time span to which the Partials -//! should be cropped. -//! \param t2 is the end of the time span to which the Partials -//! should be cropped. -// -template< class Iter > -void crop( Iter b, Iter e, double t1, double t2 ) -{ - Cropper cropper( t1, t2 ); - while ( b != e ) - { - cropper( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// TimeShifter -// -//! Shift the time of all the Breakpoints in a Partial by a -//! constant amount. -// -class TimeShifter -{ -public: - - //! Construct a new TimeShifter from a constant offset in seconds. - TimeShifter( double x ) : offset( x ) {} - - //! Function call operator: apply a time shift to the specified - //! Partial. - void operator()( Partial & p ) const; - -private: - double offset; -}; - -// --------------------------------------------------------------------------- -// shiftTime -// --------------------------------------------------------------------------- -//! Shift the time of all the Breakpoints in a Partial by a -//! constant amount. -//! -//! \param p is a Partial to shift. -//! \param offset is a constant offset in seconds. -// -inline -void shiftTime( Partial & p, double offset ) -{ - TimeShifter shifter( offset ); - shifter( p ); -} - -// --------------------------------------------------------------------------- -// shiftTime -// --------------------------------------------------------------------------- -//! Shift the time of all the Breakpoints in a Partial by a -//! constant amount. -//! -//! \param b is the beginning of a sequence of Partials to shift. -//! \param e is the end of a sequence of Partials to shift. -//! \param offset is a constant offset in seconds. -// -template< class Iter > -void shiftTime( Iter b, Iter e, double offset ) -{ - TimeShifter shifter( offset ); - while ( b != e ) - { - shifter( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// timeSpan -// --------------------------------------------------------------------------- -//! Return the time (in seconds) spanned by a specified half-open -//! range of Partials as a std::pair composed of the earliest -//! Partial start time and latest Partial end time in the range. -// -template < typename Iterator > -std::pair< double, double > -timeSpan( Iterator begin, Iterator end ) -{ - double tmin = 0., tmax = 0.; - if ( begin != end ) - { - Iterator it = begin; - tmin = it->startTime(); - tmax = it->endTime(); - while( it != end ) - { - tmin = std::min( tmin, it->startTime() ); - tmax = std::max( tmax, it->endTime() ); - ++it; - } - } - return std::make_pair( tmin, tmax ); -} - -// --------------------------------------------------------------------------- -// peakAmplitude -// --------------------------------------------------------------------------- -//! Return the maximum amplitude achieved by a Partial. -//! -//! \param p is the Partial to evaluate -//! \return the maximum (absolute) amplitude achieved by -//! the partial p -// -double peakAmplitude( const Partial & p ); - -// --------------------------------------------------------------------------- -// avgAmplitude -// --------------------------------------------------------------------------- -//! Return the average amplitude over all Breakpoints in this Partial. -//! Return zero if the Partial has no Breakpoints. -//! -//! \param p is the Partial to evaluate -//! \return the average amplitude of Breakpoints in the Partial p -// -double avgAmplitude( const Partial & p ); - -// --------------------------------------------------------------------------- -// avgFrequency -// --------------------------------------------------------------------------- -//! Return the average frequency over all Breakpoints in this Partial. -//! Return zero if the Partial has no Breakpoints. -//! -//! \param p is the Partial to evaluate -//! \return the average frequency (Hz) of Breakpoints in the Partial p -// -double avgFrequency( const Partial & p ); - -// --------------------------------------------------------------------------- -// weightedAvgFrequency -// --------------------------------------------------------------------------- -//! Return the average frequency over all Breakpoints in this Partial, -//! weighted by the Breakpoint amplitudes. -//! Return zero if the Partial has no Breakpoints. -//! -//! \param p is the Partial to evaluate -//! \return the average frequency (Hz) of Breakpoints in the Partial p -// -double weightedAvgFrequency( const Partial & p ); - -// -- phase maintenance functions -- - -// --------------------------------------------------------------------------- -// fixPhaseBefore -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints earlier than the specified time -//! so that the synthesized phases of those earlier Breakpoints matches -//! the stored phase, and the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the Partial -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the Partial. -//! -//! \param p The Partial whose phases should be fixed. -//! \param t The time before which phases should be adjusted. -// -void fixPhaseBefore( Partial & p, double t ); - -// --------------------------------------------------------------------------- -// fixPhaseBefore (range) -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints earlier than the specified time -//! so that the synthesized phases of those earlier Breakpoints matches -//! the stored phase, and the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the Partial -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the Partial. -//! -//! \param b The beginning of a range of Partials whose phases -//! should be fixed. -//! \param e The end of a range of Partials whose phases -//! should be fixed. -//! \param t The time before which phases should be adjusted. -// -template < class Iter > -void fixPhaseBefore( Iter b, Iter e, double t ) -{ - while ( b != e ) - { - fixPhaseBefore( *b, t ); - ++b; - } -} - -// --------------------------------------------------------------------------- -// fixPhaseAfter -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints later than the specified time -//! so that the synthesized phases of those later Breakpoints matches -//! the stored phase, as long as the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is simply left unmodified, -//! and future phases wil be recomputed from that one. -//! -//! \param p The Partial whose phases should be fixed. -//! \param t The time after which phases should be adjusted. -// -void fixPhaseAfter( Partial & p, double t ); - -// --------------------------------------------------------------------------- -// fixPhaseAfter (range) -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints later than the specified time -//! so that the synthesized phases of those later Breakpoints matches -//! the stored phase, as long as the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is simply left unmodified, -//! and future phases wil be recomputed from that one. -//! -//! \param b The beginning of a range of Partials whose phases -//! should be fixed. -//! \param e The end of a range of Partials whose phases -//! should be fixed. -//! \param t The time after which phases should be adjusted. -// -template < class Iter > -void fixPhaseAfter( Iter b, Iter e, double t ) -{ - while ( b != e ) - { - fixPhaseAfter( *b, t ); - ++b; - } -} - -// --------------------------------------------------------------------------- -// fixPhaseForward -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints later than the specified time -//! so that the synthesize phases of those later Breakpoints matches -//! the stored phase, as long as the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. Breakpoints later than -//! tend are unmodified. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is simply left unmodified, -//! and future phases wil be recomputed from that one. -//! -//! \param p The Partial whose phases should be fixed. -//! \param tbeg The phases and frequencies of Breakpoints later than the -//! one nearest this time will be modified. -//! \param tend The phases and frequencies of Breakpoints earlier than the -//! one nearest this time will be modified. Should be greater -//! than tbeg, or else they will be swapped. -// -void fixPhaseForward( Partial & p, double tbeg, double tend ); - -// --------------------------------------------------------------------------- -// fixPhaseForward (range) -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints later than the specified time -//! so that the synthesize phases of those later Breakpoints matches -//! the stored phase, as long as the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is simply left unmodified, -//! and future phases wil be recomputed from that one. -//! -//! \param b The beginning of a range of Partials whose phases -//! should be fixed. -//! \param e The end of a range of Partials whose phases -//! should be fixed. -//! \param tbeg The phases and frequencies of Breakpoints later than the -//! one nearest this time will be modified. -//! \param tend The phases and frequencies of Breakpoints earlier than the -//! one nearest this time will be modified. Should be greater -//! than tbeg, or else they will be swapped. -// -template < class Iter > -void fixPhaseForward( Iter b, Iter e, double tbeg, double tend ) -{ - while ( b != e ) - { - fixPhaseForward( *b, tbeg, tend ); - ++b; - } -} - - -// --------------------------------------------------------------------------- -// fixPhaseAt -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints in a Partial -//! so that the synthesized phases match the stored phases, -//! and the synthesized phase at (nearest) the specified -//! time matches the stored (not recomputed) phase. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the Partial -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the Partial. Forward phase fixing is only applied -//! to non-null (nonzero-amplitude) Breakpoints. If a null is encountered, -//! its phase is simply left unmodified, and future phases wil be -//! recomputed from that one. -//! -//! \param p The Partial whose phases should be fixed. -//! \param t The time at which phases should be made correct. -// -void fixPhaseAt( Partial & p, double t ); - -// --------------------------------------------------------------------------- -// fixPhaseAt (range) -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints in a Partial -//! so that the synthesize phases match the stored phases, -//! and the synthesized phase at (nearest) the specified -//! time matches the stored (not recomputed) phase. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the Partial -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the Partial. Forward phase fixing is only applied -//! to non-null (nonzero-amplitude) Breakpoints. If a null is encountered, -//! its phase is simply left unmodified, and future phases wil be -//! recomputed from that one. -//! -//! \param b The beginning of a range of Partials whose phases -//! should be fixed. -//! \param e The end of a range of Partials whose phases -//! should be fixed. -//! \param t The time at which phases should be made correct. -// -template < class Iter > -void fixPhaseAt( Iter b, Iter e, double t ) -{ - while ( b != e ) - { - fixPhaseAt( *b, t ); - ++b; - } -} - -// --------------------------------------------------------------------------- -// fixPhaseBetween -// --------------------------------------------------------------------------- -//! Fix the phase travel between two times by adjusting the -//! frequency and phase of Breakpoints between those two times. -//! -//! This algorithm assumes that there is nothing interesting about the -//! phases of the intervening Breakpoints, and modifies their frequencies -//! as little as possible to achieve the correct amount of phase travel -//! such that the frequencies and phases at the specified times -//! match the stored values. The phases of all the Breakpoints between -//! the specified times are recomputed. -//! -//! THIS DOES NOT YET TREAT NULL BREAKPOINTS DIFFERENTLY FROM OTHERS. -//! -//! \pre Thre must be at least one Breakpoint in the -//! Partial between the specified times t1 and t2. -//! If this condition is not met, the Partial is -//! unmodified. -//! \post The phases and frequencies of the Breakpoints in the -//! range have been recomputed such that an oscillator -//! initialized to the parameters of the first Breakpoint -//! will arrive at the parameters of the last Breakpoint, -//! and all the intervening Breakpoints will be matched. -//! \param p The partial whose phases and frequencies will be recomputed. -//! The Breakpoint at this position is unaltered. -//! \param t1 The time before which Partial frequencies and phases will -//! not be modified. -//! \param t2 The time after which Partial frequencies and phases will -//! not be modified. Should be greater than t1, or else they -//! will be swapped. -// -void fixPhaseBetween( Partial & p, double t1, double t2 ); - -// --------------------------------------------------------------------------- -// fixPhaseBetween (range) -// --------------------------------------------------------------------------- -//! Fix the phase travel between two times by adjusting the -//! frequency and phase of Breakpoints between those two times. -//! -//! This algorithm assumes that there is nothing interesting about the -//! phases of the intervening Breakpoints, and modifies their frequencies -//! as little as possible to achieve the correct amount of phase travel -//! such that the frequencies and phases at the specified times -//! match the stored values. The phases of all the Breakpoints between -//! the specified times are recomputed. -//! -//! THIS DOES NOT YET TREAT NULL BREAKPOINTS DIFFERENTLY FROM OTHERS. -//! -//! \pre Thre must be at least one Breakpoint in each -//! Partial between the specified times t1 and t2. -//! If this condition is not met, the Partial is -//! unmodified. -//! \post The phases and frequencies of the Breakpoints in the -//! range have been recomputed such that an oscillator -//! initialized to the parameters of the first Breakpoint -//! will arrive at the parameters of the last Breakpoint, -//! and all the intervening Breakpoints will be matched. -//! \param b The beginning of a range of Partials whose phases -//! should be fixed. -//! \param e The end of a range of Partials whose phases -//! should be fixed. -//! \param t1 The time before which Partial frequencies and phases will -//! not be modified. -//! \param t2 The time after which Partial frequencies and phases will -//! not be modified. Should be greater than t1, or else they -//! will be swapped. -// -template < class Iter > -void fixPhaseBetween( Iter b, Iter e, double t1, double t2 ) -{ - while ( b != e ) - { - fixPhaseBetween( *b, t1, t2 ); - ++b; - } -} - - - -// -- predicates -- - -// --------------------------------------------------------------------------- -// isDurationLess -// -//! Predicate functor returning true if the duration of its -//! Partial argument is less than the specified duration in -//! seconds, and false otherwise. -// -class isDurationLess : public std::unary_function< const Partial, bool > -{ -public: - //! Initialize a new instance with the specified label. - isDurationLess( double x ) : mDurationSecs(x) {} - - //! Function call operator: evaluate a Partial. - bool operator()( const Partial & p ) const - { return p.duration() < mDurationSecs; } - - //! Function call operator: evaluate a Partial pointer. - bool operator()( const Partial * p ) const - { return p->duration() < mDurationSecs; } - -private: - double mDurationSecs; -}; - -// --------------------------------------------------------------------------- -// isLabelEqual -// -//! Predicate functor returning true if the label of its Partial argument is -//! equal to the specified 32-bit label, and false otherwise. -// -class isLabelEqual : public std::unary_function< const Partial, bool > -{ -public: - //! Initialize a new instance with the specified label. - isLabelEqual( int l ) : label(l) {} - - //! Function call operator: evaluate a Partial. - bool operator()( const Partial & p ) const - { return p.label() == label; } - - //! Function call operator: evaluate a Partial pointer. - bool operator()( const Partial * p ) const - { return p->label() == label; } - -private: - int label; -}; - -// --------------------------------------------------------------------------- -// isLabelGreater -// -//! Predicate functor returning true if the label of its Partial argument is -//! greater than the specified 32-bit label, and false otherwise. -// -class isLabelGreater : public std::unary_function< const Partial, bool > -{ -public: - //! Initialize a new instance with the specified label. - isLabelGreater( int l ) : label(l) {} - - //! Function call operator: evaluate a Partial. - bool operator()( const Partial & p ) const - { return p.label() > label; } - - //! Function call operator: evaluate a Partial pointer. - bool operator()( const Partial * p ) const - { return p->label() > label; } - -private: - int label; -}; - -// --------------------------------------------------------------------------- -// isLabelLess -// -//! Predicate functor returning true if the label of its Partial argument is -//! less than the specified 32-bit label, and false otherwise. -// -class isLabelLess : public std::unary_function< const Partial, bool > -{ -public: - //! Initialize a new instance with the specified label. - isLabelLess( int l ) : label(l) {} - - //! Function call operator: evaluate a Partial. - bool operator()( const Partial & p ) const - { return p.label() < label; } - - //! Function call operator: evaluate a Partial pointer. - bool operator()( const Partial * p ) const - { return p->label() < label; } - -private: - int label; -}; - -// --------------------------------------------------------------------------- -// isPeakLess -// -//! Predicate functor returning true if the peak amplitude achieved by its -//! Partial argument is less than the specified absolute amplitude, and -//! false otherwise. -// -class isPeakLess : public std::unary_function< const Partial, bool > -{ -public: - //! Initialize a new instance with the specified peak amplitude. - isPeakLess( double x ) : thresh(x) {} - - //! Function call operator: evaluate a Partial. - bool operator()( const Partial & p ) const - { return peakAmplitude( p ) < thresh; } - - //! Function call operator: evaluate a Partial pointer. - bool operator()( const Partial * p ) const - { return peakAmplitude( *p ) < thresh; } - -private: - double thresh; -}; - -// -- comparitors -- - -// --------------------------------------------------------------------------- -// compareLabelLess -// -//! Comparitor (binary) functor returning true if its first Partial -//! argument has a label whose 32-bit integer representation is less than -//! that of the second Partial argument's label, and false otherwise. -// -class compareLabelLess : - public std::binary_function< const Partial, const Partial, bool > -{ -public: - //! Compare two Partials, return true if its first Partial - //! argument has a label whose 32-bit integer representation is less than - //! that of the second Partial argument's label, and false otherwise. - bool operator()( const Partial & lhs, const Partial & rhs ) const - { return lhs.label() < rhs.label(); } - - //! Compare two Partials, return true if its first Partial - //! argument has a label whose 32-bit integer representation is less than - //! that of the second Partial argument's label, and false otherwise. - bool operator()( const Partial * lhs, const Partial * rhs ) const - { return lhs->label() < rhs->label(); } -}; - -// --------------------------------------------------------------------------- -// compareDurationLess -// -//! Comparitor (binary) functor returning true if its first Partial -//! argument has duration less than that of the second Partial -//! argument, and false otherwise. -// -class compareDurationLess : - public std::binary_function< const Partial, const Partial, bool > -{ -public: - //! Compare two Partials, return true if its first Partial - //! argument has duration less than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial & lhs, const Partial & rhs ) const - { return lhs.duration() < rhs.duration(); } - - //! Compare two Partials, return true if its first Partial - //! argument has duration less than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial * lhs, const Partial * rhs ) const - { return lhs->duration() < rhs->duration(); } -}; - -// --------------------------------------------------------------------------- -// compareDurationGreater -// -//! Comparitor (binary) functor returning true if its first Partial -//! argument has duration greater than that of the second Partial -//! argument, and false otherwise. -// -class compareDurationGreater : - public std::binary_function< const Partial, const Partial, bool > -{ -public: - //! Compare two Partials, return true if its first Partial - //! argument has duration greater than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial & lhs, const Partial & rhs ) const - { return lhs.duration() > rhs.duration(); } - - //! Compare two Partials, return true if its first Partial - //! argument has duration greater than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial * lhs, const Partial * rhs ) const - { return lhs->duration() > rhs->duration(); } -}; - -// --------------------------------------------------------------------------- -// compareStartTimeLess -// -//! Comparitor (binary) functor returning true if its first Partial -//! argument has start time earlier than that of the second Partial -//! argument, and false otherwise. -// -class compareStartTimeLess : - public std::binary_function< const Partial, const Partial, bool > -{ -public: - //! Compare two Partials, return true if its first Partial - //! argument has start time earlier than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial & lhs, const Partial & rhs ) const - { return lhs.startTime() < rhs.startTime(); } - - //! Compare two Partials, return true if its first Partial - //! argument has start time earlier than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial * lhs, const Partial * rhs ) const - { return lhs->startTime() < rhs->startTime(); } -}; - - - -} // end of namespace PartialUtils - -} // end of namespace Loris - -#endif /* ndef INCLUDE_PARTIALUTILS_H */ diff --git a/loris_library/Source/include/loris/ReassignedSpectrum.h b/loris_library/Source/include/loris/ReassignedSpectrum.h deleted file mode 100644 index cd8ae69..0000000 --- a/loris_library/Source/include/loris/ReassignedSpectrum.h +++ /dev/null @@ -1,229 +0,0 @@ -#ifndef INCLUDE_REASSIGNEDSPECTRUM_H -#define INCLUDE_REASSIGNEDSPECTRUM_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * ReassignedSpectrum.h - * - * Definition of class Loris::ReassignedSpectrum. - * - * Kelly Fitz, 7 Dec 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "FourierTransform.h" -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class ReassignedSpectrum -// -//! Computes a reassigned short-time Fourier spectrum using the transform -//! method of Auger and Flandrin. -// -class ReassignedSpectrum -{ -// -- public interface -- -public: - //! An unsigned integral type large enough - //! to represent the length of any transform. - typedef FourierTransform::size_type size_type; - -// --- lifecycle --- - - //! Construct a new instance using the specified short-time window. - //! Transform lengths are the smallest power of two greater than twice the - //! window length. - ReassignedSpectrum( const std::vector< double > & window ); - - //! Construct a new instance using the specified short-time window and - //! its time derivative. - //! Transform lengths are the smallest power of two greater than twice the - //! window length. - ReassignedSpectrum( const std::vector< double > & window, - const std::vector< double > & windowDerivative ); - - // compiler-generated copy, assign, and destroy are sufficient - -// --- operations --- - - //! Compute the reassigned Fourier transform of the samples on the half open - //! range [sampsBegin, sampsEnd), aligning sampCenter with the center of - //! the analysis window. - //! - //! \param sampsBegin pointer representing the beginning of - //! the (half-open) range of samples to transform - //! \param sampCenter the sample in the range that is to be - //! aligned with the center of the analysis window - //! \param sampsEnd pointer representing the end of - //! the (half-open) range of samples to transform - //! - //! \pre sampsBegin must not be past sampCenter - //! \pre sampsEnd must be past sampCenter - //! \post the transform buffers store the reassigned - //! short-time transform data for the specified - //! samples - void transform( const double * sampsBegin, const double * pos, const double * sampsEnd ); - -// --- inquiry --- - - //! Return the length of the Fourier transforms. - size_type size( void ) const; - - //! Return read access to the short-time window samples. - //! (Peers may need to know about the analysis window - //! or about the scale factors in introduces.) - const std::vector< double > & window( void ) const; - - -// --- reassigned transform access --- - - //! Compute and return the convergence indicator, computed from the - //! mixed partial derivative of spectral phase, optionally used in - //! BW enhanced analysis as a convergence indicator. The convergence - //! value is on the range [0,1], 0 for a sinusoid, and 1 for an impulse. - //! - //! \param idx the frequency sample at which to evaluate the - //! transform - double convergence( long idx ) const; - - //! Return the reassigned frequency in fractional frequency - //! samples computed at the specified transform index. - //! - //! \param idx the frequency sample at which to evaluate the - //! transform - double reassignedFrequency( long idx ) const; - - //! Return the spectrum magnitude (absolute) - //! computed at the specified transform index. - //! - //! \param idx the frequency sample at which to evaluate the - //! transform - double reassignedMagnitude( long idx ) const; - - //! Return the phase in radians computed at the specified transform index. - //! The reassigned phase is shifted to account for the time - //! correction according to the corrected frequency. - //! - //! - //! \param idx the frequency sample at which to evaluate the - //! transform - double reassignedPhase( long idx ) const; - - //! Return the reassigned time in fractional samples - //! computed at the specified transform index. - //! - //! \param idx the frequency sample at which to evaluate the - //! transform - double reassignedTime( long idx ) const; - -// --- reassignment operations --- - - //! Compute the frequency correction at the specified frequency sample - //! using the method of Auger and Flandrin to evaluate the partial - //! derivative of spectrum phase w.r.t. time. - //! - //! Correction is computed in fractional frequency samples, because - //! that's the kind of frequency domain ramp we used on our window. - //! sample is the frequency sample index, the nominal component - //! frequency in samples. - double frequencyCorrection( long sample ) const; - - //! Compute the time correction at the specified frequency sample - //! using the method of Auger and Flandrin to evaluate the partial - //! derivative of spectrum phase w.r.t. frequency. - //! - //! Correction is computed in fractional samples, because - //! that's the kind of ramp we used on our window. - double timeCorrection( long sample ) const; - -// --- legacy support --- - - // These members are deprecated, and included only - // to support old code. New code should use the - // corresponding documented members. - // All of these members are deprecated. - - double reassignedPhase( long idx, double, double ) const - { return reassignedPhase( idx ); } - double reassignedMagnitude( double, long intBinNumber ) const - { return reassignedMagnitude( intBinNumber ); } - - // subscript operator - // The signature has changed, can no longer return a reference, - // but since the reference returned was const, this version should - // keep most old code working, if not all. - std::complex< double > operator[]( unsigned long idx ) const; - -private: - -// -- window building helpers -- - - // Build a pair of complex-valued windows, one having the frequency-ramp - // (time-derivative) window in the real part and the time-ramp window in the - // imagnary part, and the other having the unmodified window in the real part - // and, if computing mixed deriviatives, the time-ramp time-derivative window - // in the imaginary part. - // - // Input is the unmodified window function. - void buildReassignmentWindows( const std::vector< double > & window ); - - // Build a pair of complex-valued windows, one having the frequency-ramp - // (time-derivative) window in the real part and the time-ramp window in the - // imagnary part, and the other having the unmodified window in the real part - // and, if computing mixed deriviatives, the time-ramp time-derivative window - // in the imaginary part. - // - // Input is the unmodified window function and its time derivative, so the - // DFT kludge is unnecessary. - void buildReassignmentWindows( const std::vector< double > & window, - const std::vector< double > & windowDerivative ); - -// -- instance variables -- - - //! the FourierTransform for computing magnitude and phase - FourierTransform mMagnitudeTransform; - - //! the FourierTransform for computing time and frequency corrections - FourierTransform mCorrectionTransform; - - //! the original short-time analysis window samples - std::vector< double > mWindow; // W(n) - - //! the complex window used to compute the - //! magnitude/phase transform - std::vector< std::complex< double > > mCplxWin_W_Wtd; // real W(n), imag nW'(n) - - //! the complex window used to compute the - //! time/frequency correction transform - std::vector< std::complex< double > > mCplxWin_Wd_Wt; // real W'(n), imag nW(n) - -}; // end of class ReassignedSpectrum - -} // end of namespace Loris - -#endif /* ndef INCLUDE_REASSIGNEDSPECTRUM_H */ diff --git a/loris_library/Source/include/loris/Resampler.h b/loris_library/Source/include/loris/Resampler.h deleted file mode 100644 index bc45eb3..0000000 --- a/loris_library/Source/include/loris/Resampler.h +++ /dev/null @@ -1,449 +0,0 @@ -#ifndef INCLUDE_RESAMPLER_H -#define INCLUDE_RESAMPLER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Resampler.h - * - * Definition of class Resampler, for converting reassigned Partial envelopes - * into more conventional additive synthesis envelopes, having data points - * at regular time intervals. The benefits of reassigned analysis are NOT - * lost in this process, since the elimination of unreliable data and the - * reduction of temporal smearing are reflected in the resampled data. - * - * Lippold, 7 Aug 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "PartialList.h" -#include "LinearEnvelope.h" - -// begin namespace -namespace Loris { - -class Partial; - -// --------------------------------------------------------------------------- -// class Resampler -// -//! Class Resampler represents an algorithm for resampling Partial envelopes -//! at regular time intervals. Resampling makes the envelope data more suitable -//! for exchange (as SDIF data, for example) with other applications that -//! cannot process raw (continuously-distributed) reassigned data. Resampling -//! will often greatly reduce the size of the data (by greatly reducing the -//! number of Breakpoints in the Partials) without adversely affecting the -//! quality of the reconstruction. -// -class Resampler -{ -// --- public interface --- -public: -// --- lifecycle --- - - //! Initialize a Resampler having the specified uniform sampling - //! interval. Enable phase-correct resampling, in which frequencies - //! of resampled Partials are modified (using fixFrequency) such - //! that the resampled phases are achieved in synthesis. Phase- - //! correct resampling can be disabled using setPhaseCorrect. - //! - //! Resampled Partials will be composed of Breakpoints at every - //! integer multiple of the resampling interval. - //! - //! \sa setPhaseCorrect - //! \sa fixFrequency - //! - //! \param sampleInterval is the resampling interval in seconds, - //! Breakpoint data is computed at integer multiples of - //! sampleInterval seconds. - //! - //! \throw InvalidArgument if sampleInterval is not positive. - explicit Resampler( double sampleInterval ); - - - // --- use compiler-generated copy/assign/destroy --- - -// --- parameters --- - - //! Specify phase-corrected resampling, or not. If phase - //! correct, Partial frequencies are altered slightly - //! to match, as nearly as possible, the Breakpoint - //! phases after resampling. Phases are updated so that - //! the Partial frequencies and phases are consistent after - //! resampling. - //! - //! \param correctPhase is a boolean flag specifying that - //! (if true) frequency/phase correction should be - //! applied after resampling. - void setPhaseCorrect( bool correctPhase ); - -// --- resampling --- - - //! Resample the specified Partial using the stored quanitization interval. - //! The Breakpoint times will comprise a contiguous sequence of all integer - //! multiples of the sampling interval, starting and ending with the nearest - //! multiples to the ends of the Partial. If phase correct resampling is - //! specified (the default)≤ frequencies and phases are corrected to be in - //! agreement and to match as nearly as possible the resampled phases. - //! - //! Resampling is performed in-place. - //! - //! \param p is the Partial to resample - void resample( Partial & p ) const; - - //! Function call operator: same as resample( p ). - void operator() ( Partial & p ) const - { - resample( p ); - } - - //! Resample the specified Partial using the stored quanitization interval. - //! The Breakpoint times will comprise a contiguous sequence of all integer - //! multiples of the sampling interval, starting and ending with the nearest - //! multiples to the ends of the Partial. If phase correct resampling is - //! specified (the default)≤ frequencies and phases are corrected to be in - //! agreement and to match as nearly as possible the resampled phases. - //! - //! The timing envelope represents a warping of the time axis that is - //! applied during resampling. The Breakpoint times in resampled Partials - //! will a comprise contiguous sequence of all integer multiples of the - //! sampling interval between the first and last breakpoints in the timing - //! envelope, and each Breakpoint will represent the parameters of the - //! original Partial at the time that is the value of the timing envelope - //! at that instant. - //! - //! Resampling is performed in-place. - //! - //! \param p is the Partial to resample - //! - //! \param timingEnv is the timing envelope, a map of Breakpoint - //! times in resampled Partials onto parameter sampling - //! instants in the original Partials. - //! - //! \throw InvalidArgument if timingEnv has any negative breakpoint - //! times or values. - void resample( Partial & p, const LinearEnvelope & timingEnv ) const; - - //! Quantize the Breakpoint times using the specified Partial using the - //! stored quanitization interval. Each Breakpoint in the Partial is - //! replaced by a Breakpoint constructed by resampling the Partial at - //! the nearest integer multiple of the of the resampling interval. - //! - //! Quantization is performed in-place. - //! - //! \param p is the Partial to resample - void quantize( Partial & p ) const; - - - //! Resample all Partials in the specified (half-open) range using this - //! Resampler's stored quanitization interval. The Breakpoint times in - //! resampled Partials will comprise a contiguous sequence of all integer - //! multiples of the sampling interval, starting and ending with the nearest - //! multiples to the ends of the Partial. If phase correct resampling is - //! specified (the default)≤ frequencies and phases are corrected to be in - //! agreement and to match as nearly as possible the resampled phases. - //! - //! Resampling is performed in-place. - //! - //! \param begin is the beginning of the range of Partials to resample - //! \param end is (one-past) the end of the range of Partials to resample - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void resample( Iter begin, Iter end ) const; -#else - inline - void resample( PartialList::iterator begin, PartialList::iterator end ) const; -#endif - - //! Function call operator: same as resample( begin, end ). -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void operator()( Iter begin, Iter end ) const -#else - void operator()( PartialList::iterator begin, PartialList::iterator end ) const -#endif - { - resample( begin, end ); - } - - //! Resample all Partials in the specified (half-open) range using this - //! Resampler's stored quanitization interval. The Breakpoint times in - //! resampled Partials will comprise a contiguous sequence of all integer - //! multiples of the sampling interval, starting and ending with the nearest - //! multiples to the ends of the Partial. If phase correct resampling is - //! specified (the default)≤ frequencies and phases are corrected to be in - //! agreement and to match as nearly as possible the resampled phases. - //! - //! The timing envelope represents a warping of the time axis that is - //! applied during resampling. The Breakpoint times in resampled Partials - //! will a comprise contiguous sequence of all integer multiples of the - //! sampling interval between the first and last breakpoints in the timing - //! envelope, and each Breakpoint will represent the parameters of the - //! original Partial at the time that is the value of the timing envelope - //! at that instant. - //! - //! Resampling is performed in-place. - //! - //! \param begin is the beginning of the range of Partials to resample - //! \param end is (one-past) the end of the range of Partials to resample - //! \param timingEnv is the timing envelope, a map of Breakpoint - //! times in resampled Partials onto parameter sampling - //! instants in the original Partials. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void resample( Iter begin, Iter end, const LinearEnvelope & timingEnv ) const; -#else - inline - void resample( PartialList::iterator begin, PartialList::iterator end, - const LinearEnvelope & timingEnv) const; -#endif - - //! Quantize all Partials in the specified (half-open) range. - //! Each Breakpoint in the Partials is replaced by a Breakpoint - //! constructed by resampling the Partial at the nearest - //! integer multiple of the of the resampling interval. - //! - //! \param begin is the beginning of the range of Partials to quantize - //! \param end is (one-past) the end of the range of Partials to quantize - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void quantize( Iter begin, Iter end ) const; -#else - inline - void quantize( PartialList::iterator begin, PartialList::iterator end ) const; -#endif - -// -- static members -- - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Resampler using the specified resampling - //! interval, and use it to channelize a sequence of Partials. - //! - //! \param begin is the beginning of a sequence of Partials to - //! resample. - //! \param end is the end of a sequence of Partials to - //! resample. - //! \param sampleInterval is the resampling interval in seconds, - //! Breakpoint data is computed at integer multiples of - //! sampleInterval seconds. - //! \param denseResampling is a boolean flag indicating that dense - //! resamping (Breakpoint at every integer multiple of the - //! resampling interval) should be performed. If false (the - //! default), sparse resampling (Breakpoints only at multiples - //! of the resampling interval near Breakpoint times in the - //! original Partial) is performed. - //! \throw InvalidArgument if sampleInterval is not positive. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - static - void resample( Iter begin, Iter end, double sampleInterval, - bool denseResampling = false ); -#else - static inline - void resample( PartialList::iterator begin, PartialList::iterator end, - double sampleInterval, bool denseResampling = false ); -#endif - -// --- instance variables --- -private: - - //! the resampling interval in seconds - double interval_; - - //! boolean flag selecting phase-corrected resampling - //! (default is true) - bool phaseCorrect_; - -}; // end of class Resampler - -// --------------------------------------------------------------------------- -// resample (sequence of Partials) -// --------------------------------------------------------------------------- -//! Resample all Partials in the specified (half-open) range using this -//! Resampler's stored sampling interval, so that the Breakpoints in -//! the Partial envelopes will all lie on a common temporal grid. -//! The Breakpoint times in the resampled Partial will comprise a -//! contiguous sequence of integer multiples of the sampling interval, -//! beginning with the multiple nearest to the Partial's start time and -//! ending with the multiple nearest to the Partial's end time. Resampling -//! is performed in-place. -//! -//! \param begin is the beginning of the range of Partials to resample -//! \param end is (one-past) the end of the range of Partials to resample -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Resampler::resample( Iter begin, Iter end ) const -#else -inline -void Resampler::resample( PartialList::iterator begin, PartialList::iterator end ) const -#endif -{ - while ( begin != end ) - { - resample( *begin++ ); - } -} - -// --------------------------------------------------------------------------- -// resample (sequence of Partials, with timing envelope) -// --------------------------------------------------------------------------- -//! Resample all Partials in the specified (half-open) range using this -//! Resampler's stored sampling interval, so that the Breakpoints in -//! the Partial envelopes will all lie on a common temporal grid. -//! The Breakpoint times in the resampled Partial will comprise a -//! contiguous sequence of integer multiples of the sampling interval, -//! beginning with the multiple nearest to the Partial's start time and -//! ending with the multiple nearest to the Partial's end time. Resampling -//! is performed in-place. -//! -//! \param begin is the beginning of the range of Partials to resample -//! \param end is (one-past) the end of the range of Partials to resample -//! \param timingEnv is the timing envelope, a map of Breakpoint -//! times in resampled Partials onto parameter sampling -//! instants in the original Partials. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Resampler::resample( Iter begin, Iter end, const LinearEnvelope & timingEnv ) const -#else -inline -void Resampler::resample( PartialList::iterator begin, PartialList::iterator end, - const LinearEnvelope & timingEnv ) const -#endif -{ - while ( begin != end ) - { - resample( *begin++, timingEnv ); - } -} - -// --------------------------------------------------------------------------- -// quantize (sequence of Partials) -// --------------------------------------------------------------------------- -//! Quantize all Partials in the specified (half-open) range. -//! Each Breakpoint in the Partials is replaced by a Breakpoint -//! constructed by resampling the Partial at the nearest -//! integer multiple of the of the resampling interval. -//! -//! \param begin is the beginning of the range of Partials to quantize -//! \param end is (one-past) the end of the range of Partials to quantize -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Resampler::quantize( Iter begin, Iter end ) const -#else -inline -void Resampler::quantize( PartialList::iterator begin, PartialList::iterator end ) const -#endif -{ - while ( begin != end ) - { - quantize( *begin++ ); - } -} - - -// --------------------------------------------------------------------------- -// resample (static) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! phase-correct resampling to a sequence of Partials. -//! Construct a Resampler using the specified resampling -//! interval, and use it to channelize a sequence of Partials. -//! -//! \param begin is the beginning of a sequence of Partials to -//! resample. -//! \param end is the end of a sequence of Partials to -//! resample. -//! \param sampleInterval is the resampling interval in seconds, -//! Breakpoint data is computed at integer multiples of -//! sampleInterval seconds. -//! \param denseResampling is a boolean flag indicating that dense -//! resamping (Breakpoint at every integer multiple of the -//! resampling interval) should be performed. If false (the -//! default), sparse resampling (Breakpoints only at multiples -//! of the resampling interval near Breakpoint times in the -//! original Partial) is performed. -//! \throw InvalidArgument if sampleInterval is not positive. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Resampler::resample( Iter begin, Iter end, double sampleInterval, - bool denseResampling ) -#else -inline -void Resampler::resample( PartialList::iterator begin, PartialList::iterator end, - double sampleInterval, bool denseResampling ) -#endif -{ - Resampler instance( sampleInterval ); - - if ( denseResampling ) - { - instance.resample( begin, end ); - } - else - { - instance.quantize( begin, end ); - } -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_RESAMPLER_H */ - diff --git a/loris_library/Source/include/loris/SdifFile.h b/loris_library/Source/include/loris/SdifFile.h deleted file mode 100644 index 8408c28..0000000 --- a/loris_library/Source/include/loris/SdifFile.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SdifFile.h - * - * Definition of SdifFile class for Partial import and export in Loris. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Marker.h" -#include "Partial.h" -#include "PartialList.h" - -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class SdifFile -// -//! Class SdifFile represents reassigned bandwidth-enhanced Partial -//! data in a SDIF-format data file. Construction of an SdifFile -//! from a stream or filename automatically imports the Partial -//! data. -//! -//! Loris stores partials in SDIF RBEP and RBEL frames. The RBEP and RBEL -//! frame and matrix definitions are included in the SDIF file's header. -//! Each RBEP frame contains one RBEP matrix, and each row in a RBEP matrix -//! describes one breakpoint in a Loris partial. The data in RBEP matrices -//! are SDIF 32-bit floats. -//! -//! The six columns in an RBEP matrix are: partialIndex, frequency, -//! amplitude, phase, noise, timeOffset. The partialIndex uniquely -//! identifies a partial. When Loris exports SDIF data, each partial is -//! assigned a unique partialIndex. The frequency (Hz), amplitude (0..1), -//! phase (radians), and noise (bandwidth) are encoded the same as Loris -//! breakpoints. The timeOffset is an offset from the RBEP frame time, -//! specifying the exact time of the breakpoint. Loris always specifies -//! positive timeOffsets, and the breakpoint's exact time is always be -//! earlier than the next RBEP frame's time. -//! -//! Since reassigned bandwidth-enhanced partial breakpoints are -//! non-uniformly spaced in time, the RBEP frame times are also -//! non-uniformly spaced. Each RBEP frame will contain at most one -//! breakpoint for any given partial. A partial may extend over a RBEP frame -//! and have no breakpoint specified by the RBEP frame, as happens when one -//! active partial has a lower temporal density of breakpoints than other -//! active partials. -//! -//! If partials have nonzero labels in Loris, then a RBEL frame describing -//! the labeling of the partials will precede the first RBEP frame in the -//! SDIF file. The RBEL frame contains a single, two-column RBEL matrix The -//! first column is the partialIndex, and the second column specifies the -//! label for the partial. -//! -//! If markers are associated with the partials in Loris, then a RBEM frame -//! describing the markers will precede the first RBEP frame in the SDIF -//! file. The RBEM frame contains two single-column RBEM matrices. The -//! first matrix contains 32-bit floats indicating the time (in seconds) -//! for each marker. The second matrix contains UTF-8 data, the names of -//! each of the markers separated by the ASCII character 0. -//! -//! In addition to RBEP frames, Loris can also read and write SDIF 1TRC -//! frames (refer to IRCAM's SDIF web site, www.ircam.fr/sdif/, for -//! definitions of standard SDIF description types). Since 1TRC frames do -//! not represent bandwidth-enhancement or the exact timing of Loris -//! breakpoints, their use is not recommended. 1TRC capabilities are -//! provided in Loris to allow interchange with programs that are unable to -//! interpret RBEP frames. -// -class SdifFile -{ -// -- public interface -- -public: - -// -- types -- - - //! The type of marker storage in an SdifFile. - typedef std::vector< Marker > markers_type; - - //! The type of the Partial storage in an AiffFile. - typedef PartialList partials_type; - -// -- construction -- - - //! Initialize an instance of SdifFile by importing Partial data from - //! the file having the specified filename or path. - explicit SdifFile( const std::string & filename ); - - //! Initialize an instance of SdifFile with copies of the Partials - //! on the specified half-open (STL-style) range. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. -#if !defined(NO_TEMPLATE_MEMBERS) - template - SdifFile( Iter begin_partials, Iter end_partials ); -#else - SdifFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ); -#endif - - //! Initialize an empty instance of SdifFile having no Partials. - SdifFile( void ); - - // copy, assign, and delete are compiler-generated - -// -- access -- - - //! Return a reference to the Markers (see Marker.h) - //! for this SdifFile. - markers_type & markers( void ); - - //! Return a reference to the Markers (see Marker.h) - //! for this SdifFile. - const markers_type & markers( void ) const; - - //! Return a reference to the bandwidth-enhanced - //! Partials represented by this SdifFile. - partials_type & partials( void ); - - //! Return a reference to the bandwidth-enhanced - //! Partials represented by this SdifFile. - const partials_type & partials( void ) const; -// -- mutation -- - - //! Add a copy of the specified Partial to this SdifFile. - void addPartial( const Loris::Partial & p ); - - //! Add a copy of each Partial on the specified half-open (STL-style) - //! range to this SdifFile. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. -#if !defined(NO_TEMPLATE_MEMBERS) - template - void addPartials( Iter begin_partials, Iter end_partials ); -#else - void addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ); -#endif - -// -- export -- - - //! Export the envelope Partials represented by this SdifFile to - //! the file having the specified filename or path. - void write( const std::string & path ); - - //! Export the envelope Partials represented by this SdifFile to - //! the file having the specified filename or path in the 1TRC - //! format, resampled, and without phase or bandwidth information. - void write1TRC( const std::string & path ); - -// -- legacy export -- - - //! Export the Partials in the specified PartialList to a SDIF file having - //! the specified file name or path. If enhanced is true (the default), - //! reassigned bandwidth-enhanced Partial data are exported in the - //! six-column RBEP format. Otherwise, the Partial data is exported as - //! resampled sinusoidal analysis data in the 1TRC format. - //! Provided for backwards compatability. - //! - //! \deprecated This function is included only for legacy support - //! and may be removed at any time. - static void Export( const std::string & filename, - const PartialList & plist, - const bool enhanced = true ); - -private: -// -- implementation -- - partials_type partials_; // Partials to store in SDIF format - markers_type markers_; // AIFF Markers - -}; // end of class SdifFile - -// -- template members -- - -// --------------------------------------------------------------------------- -// constructor from Partial range -// --------------------------------------------------------------------------- -// Initialize an instance of SdifFile with copies of the Partials -// on the specified half-open (STL-style) range. -// -// If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -// only PartialList::const_iterator arguments. -// -#if !defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -SdifFile::SdifFile( Iter begin_partials, Iter end_partials ) -#else -SdifFile::SdifFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ) -#endif -{ - addPartials( begin_partials, end_partials ); -} - -// --------------------------------------------------------------------------- -// addPartials -// --------------------------------------------------------------------------- -// Add a copy of each Partial on the specified half-open (STL-style) -// range to this SdifFile. -// -// If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -// only PartialList::const_iterator arguments. -// -#if !defined(NO_TEMPLATE_MEMBERS) -template -void SdifFile::addPartials( Iter begin_partials, Iter end_partials ) -#else -void SdifFile::addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ) -#endif -{ - partials_.insert( partials_.end(), begin_partials, end_partials ); -} - -} // end of namespace Loris - diff --git a/loris_library/Source/include/loris/Sieve.h b/loris_library/Source/include/loris/Sieve.h deleted file mode 100644 index aff3f16..0000000 --- a/loris_library/Source/include/loris/Sieve.h +++ /dev/null @@ -1,269 +0,0 @@ -#ifndef INCLUDE_SIEVE_H -#define INCLUDE_SIEVE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Sieve.h - * - * Definition of class Sieve. - * - * Lippold Haken, 20 Jan 2001 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Distiller.h" // for default fade time and silent time - -#if defined(NO_TEMPLATE_MEMBERS) -#include "PartialList.h" -#endif - -#include "PartialPtrs.h" - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Sieve -// -//! A Sieve eliminating temporal overlap among Partials. -//! -//! Class Sieve represents an algorithm for identifying channelized (see also -//! Channelizer) Partials that overlap in time, and selecting the longer -//! one to represent the channel. The identification of overlap includes -//! the time needed for Partials to fade to and from zero amplitude in -//! synthesis (see also Synthesizer) or distillation. (see also Distiller) -//! -//! In some cases, the energy redistribution effected by the distiller -//! (see also Distiller) is undesirable. In such cases, the partials can be -//! sifted before distillation. The sifting process in Loris identifies -//! all the partials that would be rejected (and converted to noise -//! energy) by the distiller and assigns them a label of 0. These sifted -//! partials can then be identified and treated sepearately or removed -//! altogether, or they can be passed through the distiller unlabeled, and -//! crossfaded in the morphing process (see also Morpher). -//! -//! \sa Channelizer, Distiller, Morpher, Synthesizer -// -class Sieve -{ -// -- instance variables -- - - double _fadeTime; //! extra time (in seconds) added to each end of - //! a Partial when determining overlap, to accomodate - //! the fade to and from zero amplitude. - -// -- public interface -- -public: - -// -- global defaults and constants -- - - enum - { - - //! Default time in milliseconds over which Partials joined by - //! distillation fade to and from zero amplitude. Divide by - //! 1000 to use as a member function parameter. This parameter - //! should be the same in Distiller, Sieve, and Collator. - DefaultFadeTimeMs = Distiller::DefaultFadeTimeMs, - - //! Default minimum duration in milliseconds of the silent - //! (zero-amplitude) gap between two Partials joined by - //! distillation. Divide by 1000 to use as a member function - //! parameter. This parameter should be the same in Distiller, - //! Sieve, and Collator. - DefaultSilentTimeMs = Distiller::DefaultSilentTimeMs - }; - -// -- construction -- - - //! Construct a new Sieve using the specified partial fade - //! time. If unspecified, the default fade time (same as the - //! default fade time for the Distiller) is used. - //! - //! \param partialFadeTime is the extra time (in seconds) - //! added to each end of a Partial to accomodate - //! the fade to and from zero amplitude. Fade time - //! must be non-negative. A default value is used - //! if unspecified. - //! \throw InvalidArgument if partialFadeTime is negative. - explicit Sieve( double partialFadeTime = Sieve::DefaultFadeTimeMs/1000.0 ); - - // Use compiler-generated copy, assign, and destroy. - -// -- sifting -- - - //! Sift labeled Partials on the specified half-open (STL-style) - //! range. If any two Partials having same label overlap in time, keep - //! only the longer of the two Partials. Set the label of the shorter - //! duration partial to zero. No Partials are removed from the - //! sequence and the sequence order is unaltered. - //! - //! \param sift_begin is the beginning of the range of Partials to sift - //! \param sift_end is (one-past) the end of the range of Partials to sift - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then sift_begin and - //! sift_end must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void sift( Iter sift_begin, Iter sift_end ); -#else - inline - void sift( PartialList::iterator sift_begin, PartialList::iterator sift_end ); -#endif - - //! Sift labeled Partials in the specified container - //! If any two Partials having same label overlap in time, keep - //! only the longer of the two Partials. Set the label of the shorter - //! duration partial to zero. No Partials are removed from the - //! container and the container order is unaltered. - //! - //! \param partials is the collection of Partials to sift in-place - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials - //! must be a PartialList, otherwise it can be any container type - //! storing Partials that supports at least bidirectional iterators. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - void sift( Container & partials ) -#else - inline - void sift( PartialList & partials ) -#endif - { - sift( partials.begin(), partials.end() ); - } - -// -- static members -- - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Sieve using the specified Partial - //! fade time (in seconds), and use it to sift a - //! sequence of Partials. - //! - //! \param sift_begin is the beginning of the range of Partials to sift - //! \param sift_end is (one-past) the end of the range of Partials to sift - //! \param partialFadeTime is the extra time (in seconds) - //! added to each end of a Partial to accomodate - //! the fade to and from zero amplitude. The Partial fade time - //! must be non-negative. - //! \throw InvalidArgument if partialFadeTime is negative. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - static - void sift( Iter sift_begin, Iter sift_end, - double partialFadeTime ); -#else - static inline - void sift( PartialList::iterator sift_begin, PartialList::iterator sift_end, - double partialFadeTime ); -#endif - -// -- helper -- -private: - - //! Sift labeled Partials. If any two Partials having the same (non-zero) - //! label overlap in time (where overlap includes the fade time at both - //! ends of each Partial), then set the label of the Partial having the - //! shorter duration to zero. Sifting is performed on a collection of - //! pointers to Partials so that the it can be performed without changing - //! the order of the Partials in the sequence. - //! - //! \param ptrs is a collection of pointers to the Partials in the - //! sequence to be sifted. - void sift_ptrs( PartialPtrs & ptrs ); - -}; // end of class Sieve - -// --------------------------------------------------------------------------- -// sift -// --------------------------------------------------------------------------- -//! Sift labeled Partials on the specified half-open (STL-style) -//! range. If any two Partials having same label overlap in time, keep -//! only the longer of the two Partials. Set the label of the shorter -//! duration partial to zero. No Partials are removed from the -//! sequence and the sequence order is unaltered. -//! -//! \param sift_begin is the beginning of the range of Partials to sift -//! \param sift_end is (one-past) the end of the range of Partials to sift -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then sift_begin and -//! sift_end must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Sieve::sift( Iter sift_begin, Iter sift_end ) -#else -inline -void Sieve::sift( PartialList::iterator sift_begin, PartialList::iterator sift_end ) -#endif -{ - PartialPtrs ptrs; - fillPartialPtrs( sift_begin, sift_end, ptrs ); - sift_ptrs( ptrs ); -} - -// --------------------------------------------------------------------------- -// sift (static) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! Construct a Sieve using the specified Partial -//! fade time (in seconds), and use it to sift a -//! sequence of Partials. -//! -//! \param sift_begin is the beginning of the range of Partials to sift -//! \param sift_end is (one-past) the end of the range of Partials to sift -//! \param partialFadeTime is the extra time (in seconds) -//! added to each end of a Partial to accomodate -//! the fade to and from zero amplitude. The Partial fade time -//! must be non-negative. -//! \throw InvalidArgument if partialFadeTime is negative. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Sieve::sift( Iter sift_begin, Iter sift_end, - double partialFadeTime ) -#else -inline -void Sieve::sift( PartialList::iterator sift_begin, PartialList::iterator sift_end, - double partialFadeTime ) -#endif -{ - Sieve instance( partialFadeTime ); - instance.sift( sift_begin, sift_end ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_SIEVE_H */ diff --git a/loris_library/Source/include/loris/SpcFile.h b/loris_library/Source/include/loris/SpcFile.h deleted file mode 100644 index 118b30d..0000000 --- a/loris_library/Source/include/loris/SpcFile.h +++ /dev/null @@ -1,368 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpcFile.h - * - * Definition of SpcFile class for Partial import and export for - * real-time synthesis in Kyma. - * - * Spc files always represent a number of Partials that is a power of - * two. This is not necessary for purely-sinusoidal files, but might be - * (not clear) for enhanced data to be properly processed in Kyma. - * - * All of this is kind of disgusting right now. This code has evolved - * somewhat randomly, and we are awaiting full support for bandwidth- - * enhanced data in Kyma.. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "Marker.h" -#include "Partial.h" - -#if defined(NO_TEMPLATE_MEMBERS) -#include "PartialList.h" -#endif - -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class SpcFile -// -//! Class SpcFile represents a collection of reassigned bandwidth-enhanced -//! Partial data in a SPC-format envelope stream data file, used by the -//! real-time bandwidth-enhanced additive synthesizer implemented on the -//! Symbolic Sound Kyma Sound Design Workstation. Class SpcFile manages -//! file I/O and conversion between Partials and envelope parameter streams. -// -class SpcFile -{ -// -- public interface -- -public: - -// -- types -- - - //! the type of the container of Markers - //! stored with an SpcFile - typedef std::vector< Marker > markers_type; - - //! the type of the container of Partials - //! stored with an SpcFile - typedef std::vector< Partial > partials_type; - -// -- construction -- - - //! Initialize an instance of SpcFile by importing envelope parameter - //! streams from the file having the specified filename or path. - //! - //! \param filename the name of the file to import - explicit SpcFile( const std::string & filename ); - - //! Initialize an instance of SpcFile with copies of the Partials - //! on the specified half-open (STL-style) range. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. - //! - //! \param begin_partials the beginning of a range of Partials to prepare - //! for Spc export - //! \param end_partials the end of a range of Partials to prepare - //! for Spc export - //! \param midiNoteNum the fractional MIDI note number, if specified - //! (default is 60) -#if !defined(NO_TEMPLATE_MEMBERS) - template - SpcFile( Iter begin_partials, Iter end_partials, double midiNoteNum = 60 ); -#else - SpcFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double midiNoteNum = 60 ); -#endif - - //! Initialize an instance of SpcFile having the specified fractional - //! MIDI note number, and no Partials (or envelope parameter streams). - //! - //! \param midiNoteNum the fractional MIDI note number, if specified - //! (default is 60) - explicit SpcFile( double midiNoteNum = 60 ); - - // copy, assign, and delete are compiler-generated - -// -- access -- - - //! Return a reference to the MarkerContainer (see Marker.h) for this SpcFile. - markers_type & markers( void ); - - //! Return a reference to the MarkerContainer (see Marker.h) for this SpcFile. - const markers_type & markers( void ) const; - - //! Return the fractional MIDI note number assigned to this SpcFile. - //! If the sound has no definable pitch, note number 60.0 is used. - double midiNoteNumber( void ) const; - - //! Return a read-only (const) reference to the bandwidth-enhanced - //! Partials represented by the envelope parameter streams in this SpcFile. - const partials_type & partials( void ) const; - - //! Return the sampling freqency in Hz for the spc data in this - //! SpcFile. This is the rate at which Kyma must be running to ensure - //! proper playback of bandwidth-enhanced Spc data. - double sampleRate( void ) const; - -// -- mutation -- - - //! Add the specified Partial to the enevelope parameter streams - //! represented by this SpcFile. - //! - //! A SpcFile can contain only one Partial having any given (non-zero) - //! label, so an added Partial will replace a Partial having the - //! same label, if such a Partial exists. - //! - //! This may throw an InvalidArgument exception if an attempt is made - //! to add unlabeled Partials, or Partials labeled higher than the - //! allowable maximum. - //! - //! \param p the Partial to add to this SpcFile - void addPartial( const Loris::Partial & p ); - - //! Add a Partial, assigning it the specified label (and position in the - //! Spc data). - //! - //! A SpcFile can contain only one Partial having any given (non-zero) - //! label, so an added Partial will replace a Partial having the - //! same label, if such a Partial exists. - //! - //! This may throw an InvalidArgument exception if an attempt is made - //! to add unlabeled Partials, or Partials labeled higher than the - //! allowable maximum. - //! - //! \param p the Partial to add to this SpcFile - //! \param label the label to associate with this Partial in - //! the Spc file (the Partial's own label is ignored). - void addPartial( const Loris::Partial & p, int label ); - - //! Add all Partials on the specified half-open (STL-style) range - //! to the enevelope parameter streams represented by this SpcFile. - //! - //! A SpcFile can contain only one Partial having any given (non-zero) - //! label, so an added Partial will replace a Partial having the - //! same label, if such a Partial exists. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. - //! - //! This may throw an InvalidArgument exception if an attempt is made - //! to add unlabeled Partials, or Partials labeled higher than the - //! allowable maximum. - //! - //! \param begin_partials the beginning of a range of Partials - //! to add to this Spc file - //! \param end_partials the end of a range of Partials - //! to add to this Spc file -#if !defined(NO_TEMPLATE_MEMBERS) - template - void addPartials( Iter begin_partials, Iter end_partials ); -#else - void addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ); -#endif - - //! Set the fractional MIDI note number assigned to this SpcFile. - //! If the sound has no definable pitch, use note number 60.0 - //! (the default). - void setMidiNoteNumber( double nn ); - - //! Set the sampling freqency in Hz for the spc data in this - //! SpcFile. This is the rate at which Kyma must be running to ensure - //! proper playback of bandwidth-enhanced Spc data. - //! - //! The default sample rate is 44100 Hz. - void setSampleRate( double rate ); - -// -- export -- - - //! Export the phase-correct bandwidth-enhanced envelope parameter - //! streams represented by this SpcFile to the file having the specified - //! filename or path. - //! - //! A nonzero endApproachTime indicates that the Partials do not include a - //! release or decay, but rather end in a static spectrum corresponding to the - //! final Breakpoint values of the partials. The endApproachTime specifies how - //! long before the end of the sound the amplitude, frequency, and bandwidth - //! values are to be modified to make a gradual transition to the static spectrum. - //! - //! If the endApproachTime is not specified, it is assumed to be zero, - //! corresponding to Partials that decay or release normally. - //! - //! \param filename the name of the file to create - //! \param endApproachTime the duration in seconds of the gradual transition - //! to a static spectrum at the end of the sound (default 0) - void write( const std::string & filename, double endApproachTime = 0 ); - - //! Export the pure sinsoidal (omitting phase and bandwidth data) envelope - //! parameter streams represented by this SpcFile to the file having the - //! specified filename or path. - //! - //! A nonzero endApproachTime indicates that the Partials do not include a - //! release or decay, but rather end in a static spectrum corresponding to the - //! final Breakpoint values of the partials. The endApproachTime specifies how - //! long before the end of the sound the amplitude, frequency, and bandwidth - //! values are to be modified to make a gradual transition to the static spectrum. - //! - //! If the endApproachTime is not specified, it is assumed to be zero, - //! corresponding to Partials that decay or release normally. - //! - //! \param filename the name of the file to create - //! \param endApproachTime the duration in seconds of the gradual transition - //! to a static spectrum at the end of the sound (default 0) - void writeSinusoidal( const std::string & filename, double endApproachTime = 0 ); - - //! Export the envelope parameter streams represented by this SpcFile to - //! the file having the specified filename or path. Export phase-correct - //! bandwidth-enhanced envelope parameter streams if enhanced is true - //! (the default), or pure sinsoidal streams otherwise. - //! - //! A nonzero endApproachTime indicates that the Partials do not include a - //! release or decay, but rather end in a static spectrum corresponding to the - //! final Breakpoint values of the partials. The endApproachTime specifies how - //! long before the end of the sound the amplitude, frequency, and bandwidth - //! values are to be modified to make a gradual transition to the static spectrum. - //! - //! If the endApproachTime is not specified, it is assumed to be zero, - //! corresponding to Partials that decay or release normally. - //! - //! \deprecated This version of write is deprecated, use the two-argument - //! versions write and writeSinusoidal. - //! - //! \param filename the name of the file to create - //! \param enhanced flag indicating whether to export enhanced (true) - //! or sinusoidal (false) data - //! \param endApproachTime the duration in seconds of the gradual transition - //! to a static spectrum at the end of the sound (default 0) - void write( const std::string & filename, bool enhanced, - double endApproachTime = 0 ); - -private: -// -- implementation -- - partials_type partials_; //! Partials to store in Spc format - markers_type markers_; //! AIFF Markers - - double notenum_; //! fractional MIDI note number - double rate_; //! sample rate in Hz at which the data plays at the - //! correction default pitch - - static const int MinNumPartials; //! the minimum number of Partials to export (32) - //! (if necessary, extra empty (silent) Partials - //! will be exported to make up the difference between - //! the size of partials_ and the next larger power - //! of two, not less than MinNumPartials - static const double DefaultRate; //! the default Spc export sample rate in Hz (44kHz) - -// -- helpers -- - void readSpcData( const std::string & filename ); - void growPartials( partials_type::size_type sz ); - -}; // end of class SpcFile - - -// --------------------------------------------------------------------------- -// constructor from Partial range -// --------------------------------------------------------------------------- -//! Initialize an instance of SpcFile with copies of the Partials -//! on the specified half-open (STL-style) range. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. -//! -//! \param begin_partials the beginning of a range of Partials to prepare -//! for Spc export -//! \param end_partials the end of a range of Partials to prepare -//! for Spc export -//! \param midiNoteNum the fractional MIDI note number, if specified -//! (default is 60) -#if !defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -SpcFile::SpcFile( Iter begin_partials, Iter end_partials, double midiNoteNum ) : -#else -SpcFile::SpcFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double midiNoteNum ) : -#endif -// initializers: - notenum_( midiNoteNum ), - rate_( DefaultRate ) -{ - growPartials( MinNumPartials ); - addPartials( begin_partials, end_partials ); -} - -// --------------------------------------------------------------------------- -// addPartials -// --------------------------------------------------------------------------- -//! Add all Partials on the specified half-open (STL-style) range -//! to the enevelope parameter streams represented by this SpcFile. -//! -//! A SpcFile can contain only one Partial having any given (non-zero) -//! label, so an added Partial will replace a Partial having the -//! same label, if such a Partial exists. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. -//! -//! This may throw an InvalidArgument exception if an attempt is made -//! to add unlabeled Partials, or Partials labeled higher than the -//! allowable maximum. -//! -//! \param begin_partials the beginning of a range of Partials -//! to add to this Spc file -//! \param end_partials the end of a range of Partials -//! to add to this Spc file -#if !defined(NO_TEMPLATE_MEMBERS) -template -void SpcFile::addPartials( Iter begin_partials, Iter end_partials ) -#else -void SpcFile::addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ) -#endif -{ - while ( begin_partials != end_partials ) - { - // do not try to add unlabeled Partials, or - // Partials labeled beyond 256: - if ( 0 != begin_partials->label() && 257 > begin_partials->label() ) - { - addPartial( *begin_partials ); - } - ++begin_partials; - } -} - -} // end of namespace Loris - - diff --git a/loris_library/Source/include/loris/SpectralPeakSelector.h b/loris_library/Source/include/loris/SpectralPeakSelector.h deleted file mode 100644 index c55056e..0000000 --- a/loris_library/Source/include/loris/SpectralPeakSelector.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef INCLUDE_SPECTRALPEAKSELECTOR_H -#define INCLUDE_SPECTRALPEAKSELECTOR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpectralPeakSelector.h - * - * Definition of a class representing a policy for selecting energy - * peaks in a reassigned spectrum to be used in Partial formation. - * - * Kelly Fitz, 28 May 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "SpectralPeaks.h" - -// begin namespace -namespace Loris { - -class ReassignedSpectrum; - -// --------------------------------------------------------------------------- -// class SpectralPeakSelector -// -// A class representing the process of selecting -// peaks (ridges) on a reassigned time-frequency surface. -// -class SpectralPeakSelector -{ -// --- interface --- -public: - // construction: - SpectralPeakSelector( double srate, double maxTimeCorrection ); - - // Collect and return magnitude peaks in the lower half of the spectrum, - // ignoring those having frequencies below the specified minimum (in Hz), and - // those having large time corrections. - // - // If the minimumFrequency is unspecified, 0 Hz is used. - // - // There are two strategies for doing. Probably each one should be a - // separate class, but for now, they are just separate functions. - Peaks selectPeaks( ReassignedSpectrum & spectrum, double minFrequency = 0 ); - - -// --- implementation --- -private: - - // There are two strategies for doing. Probably each one should be a - // separate class, but for now, they are just separate functions. - // - // Currently, the reassignment minima are used. - - Peaks selectReassignmentMinima( ReassignedSpectrum & spectrum, double minFrequency ); - Peaks selectMagnitudePeaks( ReassignedSpectrum & spectrum, double minFrequency ); - - -// --- member data --- - - double mSampleRate; - double mMaxTimeOffset; - - -}; // end of class SpectralPeakSelector - -} // end of namespace Loris - -#endif /* ndef INCLUDE_SPECTRALPEAKSELECTOR_H */ diff --git a/loris_library/Source/include/loris/SpectralPeaks.h b/loris_library/Source/include/loris/SpectralPeaks.h deleted file mode 100644 index e5103cf..0000000 --- a/loris_library/Source/include/loris/SpectralPeaks.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef INCLUDE_SPECTRALPEAKS_H -#define INCLUDE_SPECTRALPEAKS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpectralPeaks.h - * - * Definition of a type representing a collection (vector) of - * reassigned spectral peaks or ridges. Shared by analysis policies. - * - * Kelly Fitz, 29 May 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Breakpoint.h" - -#include - -// begin namespace -namespace Loris { - -// define a spectral peak data structure -// -// HEY -// Clean this mess up! Upgrade this struct into a class that can -// store more kinds of information (like reassignment values), and -// creates a Breakpoint when needed. - -class SpectralPeak -{ -private: - - double m_time; - Breakpoint m_breakpoint; - -public: - - // --- lifecycle --- - - SpectralPeak( double t, const Breakpoint & bp ) : m_time( t ), m_breakpoint( bp ) {} - - - // --- access --- - - double time( void ) const { return m_time; } - - double amplitude( void ) const { return m_breakpoint.amplitude(); } - double frequency( void ) const { return m_breakpoint.frequency(); } - double bandwidth( void ) const { return m_breakpoint.bandwidth(); } - - // --- mutation --- - - void setAmplitude( double x ) { m_breakpoint.setAmplitude(x); } - void setBandwidth( double x ) { m_breakpoint.setBandwidth(x); } - - // this REALLY shouldn't be in here... - void addNoiseEnergy( double enoise ) { m_breakpoint.addNoiseEnergy(enoise); } - - // --- Breakpoint creation --- - - Breakpoint createBreakpoint( void ) const { return m_breakpoint; } - - // --- comparitors --- - - // Comparitor for sorting spectral peaks in order of - // increasing frequency, or finding maximum frequency. - - static bool sort_increasing_freq( const SpectralPeak & lhs, - const SpectralPeak & rhs ) - { - return lhs.frequency() < rhs.frequency(); - } - - // predicate used for sorting peaks in order of decreasing amplitude: - static bool sort_greater_amplitude( const SpectralPeak & lhs, - const SpectralPeak & rhs ) - { - return lhs.amplitude() > rhs.amplitude(); - } -}; - -// define the structure used to collect spectral peaks: -typedef std::vector< SpectralPeak > Peaks; - - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_SPECTRALPEAKS_H */ diff --git a/loris_library/Source/include/loris/SpectralSurface.h b/loris_library/Source/include/loris/SpectralSurface.h deleted file mode 100644 index 3291f3d..0000000 --- a/loris_library/Source/include/loris/SpectralSurface.h +++ /dev/null @@ -1,370 +0,0 @@ -#ifndef INCLUDE_SPECTRALSURFACE_H -#define INCLUDE_SPECTRALSURFACE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpectralSurface.h - * - * Definition of class SpectralSurface, a class representing - * a smoothed time-frequency surface that can be used to - * perform cross-synthesis, the filtering of one sound by the - * time-varying spectrum of another. - * - * Kelly Fitz, 21 Dec 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "LorisExceptions.h" -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" // for compareLabelLess - -#include // for sort -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// Class SpectralSurface -// -//! SpectralSurface represents a smoothed time-frequency surface that -//! can be used to perform cross-synthesis, the filtering of one sound -//! by the time-varying spectrum of another. -// -class SpectralSurface -{ -// -- public interface -- -public: - -// -- lifecycle -- - - //! Contsruct a new SpectralSurface from a sequence of distilled - //! Partials. - //! - //! \pre the specified Partials must be channelized and distilled. - //! \param b the beginning of the sequence of Partials - //! \param e the end of the sequence of Partials - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - SpectralSurface( Iter b, Iter e ); -#else - inline - SpectralSurface( PartialList::iterator b, PartialList::iterator e ); -#endif - - // use compiler-generated copy/assign/destroy - -// --- operations --- - - //! Scale the amplitude of every Breakpoint in a Partial - //! according to the amplitude of the spectral surface - //! at the corresponding time and frequency. - //! - //! \param p the Partial to modify - void scaleAmplitudes( Partial & p ); - - //! Scale the amplitudes of a sequence of Partials - //! according to the amplitude of the spectral surface - //! at the corresponding times and frequencies, - //! performing cross-synthesis, the filtering of one - //! sound (the sequence of Partials) by the time-varying - //! spectrum of another sound (the Partials used to - //! construct the surface). The surface is stretched - //! in time and frequency according to the values of - //! the two stretch factors (default 1, no stretching) - //! and the amount of the effect is governed by the - //! `effect' parameter (default 1, full effect). - //! - //! \param b the beginning of the sequence of Partials - //! \param e the end of the sequence of Partials - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void scaleAmplitudes( Iter b, Iter e ); -#else - inline - void scaleAmplitudes( PartialList::iterator b, PartialList::iterator e ); -#endif - - //! Set the amplitude of every Breakpoint in a Partial - //! equal to the amplitude of the spectral surface - //! at the corresponding time and frequency. - //! - //! \param p the Partial to modify - void setAmplitudes( Partial & p ); - - //! Set the amplitudes of a sequence of Partials - //! equal to the amplitude of the spectral surface - //! at the corresponding times and frequencies. - //! This can be used to perform formant-corrected - //! pitch shifting of a sound: construct the surface - //! from the unmodified Partials, perform the pitch - //! shift on the Partials, then apply the surface - //! to the shifted Partials using setAmplitudes. - //! The surface is stretched - //! in time and frequency according to the values of - //! the two stretch factors (default 1, no stretching) - //! and the amount of the effect is governed by the - //! `effect' parameter (default 1, full effect). - //! - //! \param b the beginning of the sequence of Partials - //! \param e the end of the sequence of Partials - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void setAmplitudes( Iter b, Iter e ); -#else - inline - void setAmplitudes( PartialList::iterator b, PartialList::iterator e ); -#endif - -// --- access/mutation --- - - //! Return the amount of strecthing in the frequency dimension - //! (default 1, no stretching). Values greater than 1 stretch - //! the surface in the frequency dimension, values less than 1 - //! (but greater than 0) compress the surface in the frequency - //! dimension. - double frequencyStretch( void ) const; - - //! Return the amount of strecthing in the time dimension - //! (default 1, no stretching). Values greater than 1 stretch - //! the surface in the time dimension, values less than 1 - //! (but greater than 0) compress the surface in the time - //! dimension. - double timeStretch( void ) const; - - //! Return the amount of effect applied by scaleAmplitudes - //! and setAmplitudes (default 1, full effect). Values - //! less than 1 (but greater than 0) reduce the amount of - //! amplitude modified performed by application of the - //! surface. (This is rarely a good way of controlling the - //! amount of the effect.) - double effect( void ) const; - - //! Set the amount of strecthing in the frequency dimension - //! (default 1, no stretching). Values greater than 1 stretch - //! the surface in the frequency dimension, values less than 1 - //! (but greater than 0) compress the surface in the frequency - //! dimension. - //! - //! \pre stretch must be positive - //! \param stretch the new stretch factor for the frequency dimension - void setFrequencyStretch( double stretch ); - - //! Set the amount of strecthing in the time dimension - //! (default 1, no stretching). Values greater than 1 stretch - //! the surface in the time dimension, values less than 1 - //! (but greater than 0) compress the surface in the time - //! dimension. - //! - //! \pre stretch must be positive - //! \param stretch the new stretch factor for the time dimension - void setTimeStretch( double stretch ); - - //! Set the amount of effect applied by scaleAmplitudes - //! and setAmplitudes (default 1, full effect). Values - //! less than 1 (but greater than 0) reduce the amount of - //! amplitude modified performed by application of the - //! surface. (This is rarely a good way of controlling the - //! amount of the effect.) - //! - //! \pre effect must be between 0 and 1, inclusive - //! \param effect the new factor controlling the amount of - //! amplitude modification performed by scaleAmplitudes - //! and setAmplitudes - void setEffect( double effect ); - -private: - -// -- instance variables -- - - std::vector< Partial > mPartials; //! the Partials comprising the surface are - //! stored in a vector for easy random access - double mStretchFreq; //! stretch factor for the frequency dimension - double mStretchTime; //! stretch factor for the time dimension - double mEffect; //! factor for controlling the amount of - //! of the effect applied in setAmplitudes and - //! scaleAmplitudes: 0 gives unmodified amplitudes - //! 1 gives fully modified amplitudes. - double mMaxSurfaceAmp; //! the maximum amplitude of any Breakpoint on - //! the surface, used for normalizing the surface - //! amplitude for scaleAmplitudes - -// --- private helpers --- - - // helper used by constructor for adding Partials one by one - void addPartialAux( const Partial & p ); - -}; - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Contsruct a new SpectralSurface from a sequence of distilled -//! Partials. -//! -//! \pre the specified Partials must be channelized and distilled. -//! \param b the beginning of the sequence of Partials -//! \param e the end of the sequence of Partials -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -SpectralSurface::SpectralSurface( Iter b, Iter e ) : -#else -inline -SpectralSurface::SpectralSurface( PartialList::iterator b, - PartialList::iterator e ) : -#endif - mStretchFreq( 1.0 ), - mStretchTime( 1.0 ), - mEffect( 1.0 ), - mMaxSurfaceAmp( 0.0 ) -{ - // add only labeled Partials: - while ( b != e ) - { - if ( b->label() != 0 ) - { - addPartialAux( *b ); - } - ++b; - } - - // complain if the Partials were not distilled - if ( mPartials.empty() ) - { - Throw( InvalidArgument, "Partals need to be distilled to build a SpectralSurface" ); - } - - if ( 0 == mMaxSurfaceAmp ) - { - Throw( InvalidArgument, "The SpectralSurface is zero amplitude everywhere!" ); - } - - // sort by label - std::sort( mPartials.begin(), mPartials.end(), PartialUtils::compareLabelLess() ); -} - - -// --------------------------------------------------------------------------- -// scaleAmplitudes -// --------------------------------------------------------------------------- -//! Scale the amplitudes of a sequence of Partials -//! according to the amplitude of the spectral surface -//! at the corresponding times and frequencies, -//! performing cross-synthesis, the filtering of one -//! sound (the sequence of Partials) by the time-varying -//! spectrum of another sound (the Partials used to -//! construct the surface). The surface is stretched -//! in time and frequency according to the values of -//! the two stretch factors (default 1, no stretching) -//! and the amount of the effect is governed by the -//! `effect' parameter (default 1, full effect). -//! -//! \param b the beginning of the sequence of Partials -//! \param e the end of the sequence of Partials -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void SpectralSurface::scaleAmplitudes( Iter b, Iter e ) -#else -inline -void SpectralSurface::scaleAmplitudes( PartialList::iterator b, - PartialList::iterator e ) -#endif -{ - while ( b != e ) - { - // debugger << b->label() << endl; - scaleAmplitudes( *b ); - ++b; - } -} - -// --------------------------------------------------------------------------- -// setAmplitudes -// --------------------------------------------------------------------------- -//! Set the amplitudes of a sequence of Partials -//! equal to the amplitude of the spectral surface -//! at the corresponding times and frequencies. -//! This can be used to perform formant-corrected -//! pitch shifting of a sound: construct the surface -//! from the unmodified Partials, perform the pitch -//! shift on the Partials, then apply the surface -//! to the shifted Partials using setAmplitudes. -//! The surface is stretched -//! in time and frequency according to the values of -//! the two stretch factors (default 1, no stretching) -//! and the amount of the effect is governed by the -//! `effect' parameter (default 1, full effect). -//! -//! \param b the beginning of the sequence of Partials -//! \param e the end of the sequence of Partials -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void SpectralSurface::setAmplitudes( Iter b, Iter e ) -#else -inline -void SpectralSurface::setAmplitudes( PartialList::iterator b, - PartialList::iterator e ) -#endif -{ - while ( b != e ) - { - // debugger << b->label() << endl; - setAmplitudes( *b ); - ++b; - } -} - -} // namespace Loris - -#endif /* ndef INCLUDE_SPECTRALSURFACE_H */ - diff --git a/loris_library/Source/include/loris/Synthesizer.h b/loris_library/Source/include/loris/Synthesizer.h deleted file mode 100644 index e0268ba..0000000 --- a/loris_library/Source/include/loris/Synthesizer.h +++ /dev/null @@ -1,391 +0,0 @@ -#ifndef INCLUDE_SYNTHESIZER_H -#define INCLUDE_SYNTHESIZER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Synthesizer.h - * - * Definition of class Loris::Synthesizer, a renderer of - * bandwidth-enhanced Partials. - * - * Kelly Fitz, 16 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - - - // TODO: - // Passing the sample vector in to Synthesizer no longer makes any sense, - // if the Synthesizer can (must) resize the buffer anyway, it may as well - // own it. In a future version, the Synthesizer owns a vector (need to add - // a method to clear it), and provides access to it (as it currently does). - // When this change is made, it probably makes sense to remove the function - // call operators. - - -#include "Oscillator.h" -#include "PartialList.h" -#include "PartialUtils.h" - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Synthesizer -// -//! A Synthesizer renders bandwidth-enhanced Partials into a buffer -//! of samples. -//! -//! Class Synthesizer represents an algorithm for rendering -//! bandwidth-enhanced Partials as floating point (double) samples at a -//! specified sampling rate, and accumulating them into a buffer. -//! -//! The Synthesizer does not own the sample buffer, the client is responsible -//! for its construction and destruction, and many Synthesizers may share -//! a buffer. -// -class Synthesizer -{ -// -- public interface -- -public: -// -- construction -- - - struct Parameters; // defined below - - //! Construct a Synthesizer using the default parameters and sample - //! buffer (a standard library vector). Since Partials generated by - //! the Loris Analyzer generally begin and end at non-zero amplitude, - //! zero-amplitude Breakpoints are inserted at either end of the Partial, - //! at a temporal distance equal to the fade time, to reduce turn-on and - //! turn-off artifacts. - //! - //! \sa Synthesizer::Parameters - //! - //! \param buffer The vector (of doubles) into which rendered samples - //! should be accumulated. - //! \throw InvalidArgument if any of the parameters is invalid. - Synthesizer( std::vector & buffer ); - - - //! Construct a Synthesizer using the specified parameters and sample - //! buffer (a standard library vector). Since Partials generated by the - //! Loris Analyzer generally begin and end at non-zero amplitude, zero-amplitude - //! Breakpoints are inserted at either end of the Partial, at a temporal - //! distance equal to the fade time, to reduce turn-on and turn-off - //! artifacts. - //! - //! \param params A Parameters struct storing the configuration of - //! Synthesizer parameters. - //! \param buffer The vector (of doubles) into which rendered samples - //! should be accumulated. - //! \throw InvalidArgument if any of the parameters is invalid. - Synthesizer( Parameters params, std::vector & buffer ); - - //! Construct a Synthesizer using the specified sampling rate, sample - //! buffer (a standard library vector), and the default fade time - //! stored in the DefaultParameters. Since Partials generated by the Loris - //! Analyzer generally begin and end at non-zero amplitude, zero-amplitude - //! Breakpoints are inserted at either end of the Partial, at a temporal - //! distance equal to the fade time, to reduce turn-on and turn-off - //! artifacts. - //! - //! \param srate The rate (Hz) at which to synthesize samples - //! (must be positive). - //! \param buffer The vector (of doubles) into which rendered samples - //! should be accumulated. - //! \throw InvalidArgument if the specfied sample rate is non-positive. - Synthesizer( double srate, std::vector & buffer ); - - //! Construct a Synthesizer using the specified sampling rate, sample - //! buffer (a standard library vector), and Partial fade time - //! (in seconds). Since Partials generated by the Loris Analyzer - //! generally begin and end at non-zero amplitude, zero-amplitude - //! Breakpoints are inserted at either end of the Partial, at a temporal - //! distance equal to the fade time, to reduce turn-on and turn-off - //! artifacts. - //! - //! \param srate The rate (Hz) at which to synthesize samples - //! (must be positive). - //! \param buffer The vector (of doubles) into which rendered samples - //! should be accumulated. - //! \param fadeTime The Partial fade time in seconds (must be non-negative). - //! \throw InvalidArgument if the specfied sample rate is non-positive. - //! \throw InvalidArgument if the specified fade time is negative. - Synthesizer( double srate, std::vector & buffer, double fadeTime ); - - // Compiler can generate copy, assign, and destroy. - // Synthesizer( const Synthesizer & other ); - // ~Synthesizer( void ); - // Synthesizer & operator= ( const Synthesizer & other ); - -// -- synthesis -- - - //! Synthesize a bandwidth-enhanced sinusoidal Partial. Zero-amplitude - //! Breakpoints are inserted at either end of the Partial to reduce - //! turn-on and turn-off artifacts, as described above. The synthesizer - //! will resize the buffer as necessary to accommodate all the samples, - //! including the fade out. Previous contents of the buffer are not - //! overwritten. Partials with start times earlier than the Partial fade - //! time will have shorter onset fades. Partials are not rendered at - //! frequencies above the half-sample rate. - //! - //! \param p The Partial to synthesize. - //! \return Nothing. - //! \pre The partial must have non-negative start time. - //! \post This Synthesizer's sample buffer (vector) has been - //! resized to accommodate the entire duration of the - //! Partial, p, including fade out at the end. - //! \throw InvalidPartial if the Partial has negative start time. - void synthesize( Partial p ); - - //! Function call operator: same as synthesize( p ). - void operator() ( const Partial & p ) { synthesize( p ) ; } - - - //! Synthesize all Partials on the specified half-open (STL-style) range. - //! Null Breakpoints are inserted at either end of the Partial to reduce - //! turn-on and turn-off artifacts, as described above. The synthesizer - //! will resize the buffer as necessary to accommodate all the samples, - //! including the fade outs. Previous contents of the buffer are not - //! overwritten. Partials with start times earlier than the Partial fade - //! time will have shorter onset fades. Partials are not rendered at - //! frequencies above the half-sample rate. - //! - //! \param begin_partials The beginning of the range of Partials - //! to synthesize. - //! \param end_partials The end of the range of Partials - //! to synthesize. - //! \return Nothing. - //! \pre The partials must have non-negative start times. - //! \post This Synthesizer's sample buffer (vector) has been - //! resized to accommodate the entire duration of all the - //! Partials including fade out at the ends. - //! \throw InvalidPartial if any Partial has negative start time. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - void synthesize( Iter begin_partials, Iter end_partials ); -#else - inline - void synthesize( PartialList::iterator begin_partials, - PartialList::iterator end_partials ); -#endif - - //! Function call operator: same as - //! synthesize( begin_partials, end_partials ). -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - void operator() ( Iter begin_partials, Iter end_partials ); -#else - inline - void operator() ( PartialList::iterator begin_partials, - PartialList::iterator end_partials ); -#endif - -// -- sample access -- - - //! Return a const reference to the sample buffer used (not - //! owned) by this Synthesizer. - const std::vector & samples( void ) const; - - //! Return a reference to the sample buffer used (not - //! owned) by this Synthesizer. - std::vector & samples( void ); - - -// -- parameter access and mutation -- - - - //! Return this Synthesizer's Partial fade time, in seconds. - double fadeTime( void ) const; - - //! Return the sampling rate (in Hz) for this Synthesizer. - double sampleRate( void ) const; - - //! Set this Synthesizer's fade time to the specified value - //! (in seconds, must be non-negative). - //! - //! \param partialFadeTime The new Partial fade time. - //! \throw InvalidArgument if the specified fade time is negative. - void setFadeTime( double partialFadeTime ); - - //! Set this Synthesizer's sample rate to the specified value - //! (in Hz, must be positive). - //! - //! \param rate The new synthesis sample rate. - //! \throw InvalidArgument if the specified rate is nonpositive. - void setSampleRate( double rate ); - - //! Return access to the Filter used by this Synthesizer's - //! Oscillator to implement bandwidth-enhanced sinusoidal - //! synthesis. (Can use this access to make changes to the - //! filter coefficients.) - Filter & filter( void ); - - -// -- parameters structure -- - - enum - { - Default_FadeTime_Ms = 1, - Default_SampleRate_Hz = 44100 - }; - - // enum EnhancementFlag { Sinusoidal = 0, BwEnhanced = 1 }; - - //! Structure storing a configuration of Synthesizer parameters. - //! Elements in this struct can be freely modified, the configuration - //! is validated before it can be used to construct a Synthesizer. - //! - //! \sa IsValidParameters - struct Parameters - { - double fadeTime; - double sampleRate; - // EnhancementFlag enhancement; - - Filter filter; - - // default constructor - // - //! Assign default initial values to the Synthesizer parameters, Filter - //! defaults are defined in Filter.C, others in Synthesizer.C. - Parameters( void ); - - // copy, assign, and destroy are free - }; - - //! Default configuration of a Loris::Synthesizer. Modify the values - //! in this structure to alter the configuration of all Synthesizers, - //! including those used by the AiffFile class to render Partials. - static const Parameters & DefaultParameters( void ); - - //! Assign a new default configuration of a Loris::Synthesizer - //! to alter the configuration of all Synthesizers, - //! including those used by the AiffFile class to render Partials. - //! - //! \param params A Parameters struct describing the new default - //! configuration for Synthesizers. - //! \throw InvalidArgument if params reprsents an invalid configuration. - static void SetDefaultParameters( const Parameters & params ); - - //! Check the validty of a Parameters structure. Returns true if the - //! struct represents a valid Synthesizer configuration, otherwise - //! raise InvalidArgument reporting the specific error. - //! - //! \param params A Parameters struct describing a configuration for - //! Synthesizers. - //! \throw InvalidArgument if params reprsents an invalid configuration. - static bool IsValidParameters( const Parameters & params ); - - -// -- implementation -- -private: - - Oscillator m_osc; // the Synthesizer has-a Oscillator that it uses to render - // all the Partials one by one. - - std::vector< double > * m_sampleBuffer; // samples are computed and stored here, BUT - // Synthesizer does NOT own this buffer. - - double m_fadeTimeSec; // Partial fade in/out time in seconds - double m_srateHz; // sample rate in Hz - -}; // end of class Synthesizer - - -// --------------------------------------------------------------------------- -// synthesize -// --------------------------------------------------------------------------- -//! Synthesize all Partials on the specified half-open (STL-style) range. -//! Null Breakpoints are inserted at either end of the Partial to reduce -//! turn-on and turn-off artifacts, as described above. The synthesizer -//! will resize the buffer as necessary to accommodate all the samples, -//! including the fade outs. Previous contents of the buffer are not -//! overwritten. Partials with start times earlier than the Partial fade -//! time will have shorter onset fades. -//! -//! \param begin_partials The beginning of the range of Partials -//! to synthesize. -//! \param end_partials The end of the range of Partials -//! to synthesize. -//! \return Nothing. -//! \pre The partials must have non-negative start times. -//! \post This Synthesizer's sample buffer (vector) has been -//! resized to accommodate the entire duration of all the -//! Partials including fade out at the ends. -//! \throw InvalidPartial if any Partial has negative start time. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void -Synthesizer::synthesize( Iter begin_partials, Iter end_partials ) -#else -inline void -Synthesizer::synthesize( PartialList::iterator begin_partials, - PartialList::iterator end_partials ) -#endif -{ - // grow the sample buffer, if necessary, to accommodate the latest - // Partial, with the fade time tacked on the end - double duration = - PartialUtils::timeSpan( begin_partials, end_partials ).second + - m_fadeTimeSec; - - typedef std::vector< double >::size_type Sz_Type; - Sz_Type Nsamps = 1 + Sz_Type( duration * m_srateHz ); - if ( m_sampleBuffer->size() < Nsamps ) - { - m_sampleBuffer->resize( Nsamps ); - } - - while ( begin_partials != end_partials ) - { - synthesize( *(begin_partials++) ); - } -} - -// --------------------------------------------------------------------------- -// operator() -// --------------------------------------------------------------------------- -//! Function call operator: same as -//! synthesize( begin_partials, end_partials, timeShift ). -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void -Synthesizer::operator() ( Iter begin_partials, Iter end_partials ) -#else -inline void -Synthesizer::operator() ( PartialList::iterator begin_partials, - PartialList::iterator end_partials ) -#endif -{ - synthesize( begin_partials, end_partials ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_SYNTHESIZER_H */ diff --git a/loris_library/Source/include/loris/lorisException_pi.h b/loris_library/Source/include/loris/lorisException_pi.h deleted file mode 100644 index 8dddc2a..0000000 --- a/loris_library/Source/include/loris/lorisException_pi.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef INCLUDE_LORISEXCEPTION_PI_H -#define INCLUDE_LORISEXCEPTION_PI_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * lorisException_pi.h - * - * A component of the C-linkable procedural interface for Loris. - * - * Main components of the Loris procedural interface: - * - object interfaces - Analyzer, Synthesizer, Partial, PartialIterator, - * PartialList, PartialListIterator, Breakpoint, BreakpointEnvelope, - * and SampleVector need to be (opaque) objects in the interface, - * either because they hold state (e.g. Analyzer) or because they are - * fundamental data types (e.g. Partial), so they need a procedural - * interface to their member functions. All these things need to be - * opaque pointers for the benefit of C. - * - non-object-based procedures - other classes in Loris are not so stateful, - * and have sufficiently narrow functionality that they need only - * procedures, and no object representation. - * - utility functions - some procedures that are generally useful but are - * not yet part of the Loris core are also defined. - * - notification and exception handlers - all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function (the default one in Loris uses printf()). - * - * This file declares the exception handling functions used in the - * Loris procedural interface. - * - * Kelly Fitz, 10 Nov 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "LorisExceptions.h" -#include - -// forward-declare local exception handler: -void handleException( const char * s ); - -/* ---------------------------------------------------------------- */ -/* class NullPointer -/* -/* Exception subclass for catching NULL pointers: - */ -class NullPointer : public Loris::Exception -{ -public: - NullPointer( const std::string & str, const std::string & where = "" ) : - Exception( std::string("NULL pointer exception -- ").append( str ), where ) {} -}; // end of class NullPointer - -#define ThrowIfNull(ptr) if ((ptr)==NULL) Throw( NullPointer, #ptr ); - - -#endif /* ndef INCLUDE_LORISEXCEPTION_PI_H */ diff --git a/loris_library/Source/include/loris/phasefix.h b/loris_library/Source/include/loris/phasefix.h deleted file mode 100644 index 016983d..0000000 --- a/loris_library/Source/include/loris/phasefix.h +++ /dev/null @@ -1,237 +0,0 @@ -#ifndef PHASEFIX_H -#define PHASEFIX_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * phasefix.h - * - * Functions for correcting Breakpoint phases and frequencies so that - * stored phases match the phases that would be synthesized using the - * Loris Synthesizer. - * - * Kelly Fitz, 23 Sept 04 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "Partial.h" - -// begin namespace -namespace Loris { - -// FUNCTION PROTOYPES - -// fixPhaseBackward -// -//! Recompute phases of all Breakpoints on the half-open range [stopHere, pos) -//! so that the synthesized phases of those Breakpoints matches -//! the stored phase, as long as the synthesized phase at stopHere -//! matches the stored (not recomputed) phase. -//! -//! The phase is corrected beginning at the end of the range, maintaining -//! the stored phase in the Breakpoint at pos. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the range -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the stopHere. -//! -//! \pre pos and stopHere are iterators on the same Partial, and -//! pos must be not later than stopHere. -//! \pre pos cannot be end of the Partial, it must be the postion -//! of a valid Breakpoint. -//! \param stopHere the position of the earliest Breakpoint whose phase might be -//! recomputed. -//! \param pos the position of a (later) Breakpoint whose phase is to be matched. -//! The phase at pos is not modified. -// -void fixPhaseBackward( Partial::iterator stopHere, Partial::iterator pos ); - -// fixPhaseForward -// -//! Recompute phases of all Breakpoints on the closed range [pos, stopHere] -//! so that the synthesized phases of those Breakpoints matches -//! the stored phase, as long as the synthesized phase at pos -//! matches the stored (not recomputed) phase. The phase at pos -//! is modified only if pos is the position of a null Breakpoint -//! and the Breakpoint that follows is non-null. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is corrected from its non-Null -//! successor, if it has one, otherwise it is unmodified. -//! -//! \pre pos and stopHere are iterators on the same Partial, and -//! pos must be not later than stopHere. -//! \pre stopHere cannot be end of the Partial, it must be the postion -//! of a valid Breakpoint. -//! \param pos the position of the first Breakpoint whose phase might be -//! recomputed. -//! \param stopHere the position of the last Breakpoint whose phase might -//! be modified. -// -void fixPhaseForward( Partial::iterator pos, Partial::iterator stopHere ); - -// --------------------------------------------------------------------------- -// fixPhaseBetween -// -//! Fix the phase travel between two Breakpoints by adjusting the -//! frequency and phase of Breakpoints between those two. -//! -//! This algorithm assumes that there is nothing interesting about the -//! phases of the intervening Breakpoints, and modifies their frequencies -//! as little as possible to achieve the correct amount of phase travel -//! such that the frequencies and phases at the specified times -//! match the stored values. The phases of all the Breakpoints between -//! the specified times are recomputed. -//! -//! Null Breakpoints are treated the same as non-null Breakpoints. -//! -//! \pre b and e are iterators on the same Partials, and -//! e must not preceed b in that Partial. -//! \pre There must be at least one Breakpoint in the -//! Partial between b and e. -//! \post The phases and frequencies of the Breakpoints in the -//! range have been recomputed such that an oscillator -//! initialized to the parameters of the first Breakpoint -//! will arrive at the parameters of the last Breakpoint, -//! and all the intervening Breakpoints will be matched. -//! \param b The phases and frequencies of Breakpoints later than -//! this one may be modified. -//! \param e The phases and frequencies of Breakpoints earlier than -//! this one may be modified. -// -void fixPhaseBetween( Partial::iterator b, Partial::iterator e ); - -// fixFrequency -// -//! Adjust frequencies of the Breakpoints in the -//! specified Partial such that the rendered Partial -//! achieves (or matches as nearly as possible, within -//! the constraint of the maximum allowable frequency -//! alteration) the analyzed phases. -//! -//! \param partial The Partial whose frequencies, -//! and possibly phases (if the frequencies -//! cannot be sufficiently altered to match -//! the phases), will be recomputed. -//! \param maxFixPct The maximum allowable frequency -//! alteration, default is 0.2%. -// -void fixFrequency( Partial & partial, double maxFixPct = 0.2 ); - -// fixFrequency -// -//! Adjust frequencies of the Breakpoints in the -//! specified Partials such that the rendered Partial -//! achieves (or matches as nearly as possible, within -//! the constraint of the maximum allowable frequency -//! alteration) the analyzed phases. -//! -//! \param b The beginning of a range of Partials whose -//! frequencies should be fixed. -//! \param e The end of a range of Partials whose frequencies -//! should be fixed. -//! \param maxFixPct The maximum allowable frequency -//! alteration, default is 0.2%. -// -template < class Iter > -void fixFrequency( Iter b, Iter e, double maxFixPct = 0.2 ) -{ - while ( b != e ) - { - fixFrequency( *b, maxFixPct ); - ++b; - } -} - -// --------------------- useful phase maintenance utilities --------------------- - -// matchPhaseFwd -// -//! Compute the target frequency that will affect the -//! predicted (by the Breakpoint phases) amount of -//! sinusoidal phase travel between two breakpoints, -//! and assign that frequency to the target Breakpoint. -//! After computing the new frequency, update the phase of -//! the later Breakpoint. -//! -//! The most common kinds of errors are local (or burst) errors in -//! frequency and phase. These errors are best corrected by correcting -//! less than half the detected error at any time. Correcting more -//! than that will produce frequency oscillations for the remainder of -//! the Partial, in the case of a single bad frequency (as is common -//! at the onset of a tone). Any damping factor less then one will -//! converge eventually, .5 or less will converge without oscillating. -//! Use the damping argument to control the damping of the correction. -//! Specify 1 for no damping. -//! -//! -//! \pre The two Breakpoints are assumed to be consecutive in -//! a Partial. -//! \param bp0 The earlier Breakpoint. -//! \param bp1 The later Breakpoint. -//! \param dt The time (in seconds) between bp0 and bp1. -//! \param damping The fraction of the amount of phase error that will -//! be corrected (.5 or less will prevent frequency oscilation -//! due to burst errors in phase). -//! \param maxFixPct The maximum amount of frequency adjustment -//! that can be made to the frequency of bp1, expressed -//! as a precentage of the unmodified frequency of bp1. -//! If the necessary amount of frequency adjustment exceeds -//! this amount, then the phase will not be matched, -//! but will be updated as well to be consistent with -//! the frequencies. (default is 0.2%) -// -void matchPhaseFwd( Breakpoint & bp0, Breakpoint & bp1, - double dt, double damping, double maxFixPct = 0.2 ); - -// phaseTravel -// -//! Compute the sinusoidal phase travel between two Breakpoints. -//! Return the total unwrapped phase travel. -//! -//! \pre The two Breakpoints are assumed to be consecutive in -//! a Partial. -//! \param bp0 The earlier Breakpoint. -//! \param bp1 The later Breakpoint. -//! \param dt The time (in seconds) between bp0 and bp1. -//! \return The total unwrapped phase travel in radians. -// -double phaseTravel( const Breakpoint & bp0, const Breakpoint & bp1, double dt ); - -// wrapPi -// -//! Wrap an unwrapped phase value to the range (-pi,pi]. -//! -//! \param x The unwrapped phase in radians. -//! \return The phase (in radians) wrapped to the range (-Pi,Pi]. -// -double wrapPi( double x ); - - -} // end of namespace Loris - -#endif // ndef PHASEFIX_H - diff --git a/loris_library/Source/public.cpp b/loris_library/Source/public.cpp deleted file mode 100644 index 6c8b6ca..0000000 --- a/loris_library/Source/public.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* - * This file is part of the HISE loris_library codebase (https://github.com/christophhart/loris-tools). - * Copyright (c) 2023 Christoph Hart - * - * 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, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "LorisState.h" -#include "public.h" - - -static loris2hise::MultichannelPartialList* getExisting(void* state, const char* file) -{ - auto typed = (loris2hise::LorisState*)state; - juce::File f(file); - - return typed->getExisting(f); -} - -extern "C" -{ - -void* createLorisState() -{ - return loris2hise::LorisState::getCurrentInstance(true); -} - -void destroyLorisState(void* stateToDestroy) -{ - delete (loris2hise::LorisState*)stateToDestroy; -} - -const char* getLibraryVersion() -{ - return ProjectInfo::versionString; -} - -const char* getLorisVersion() -{ - return LORIS_VERSION_STR; -} - -size_t getRequiredBytes(void* state, const char* file) -{ - loris2hise::LorisState::resetState(state); - - if (auto s = getExisting(state, file)) - return s->getRequiredBytes(); - - return 0; -} - -bool loris_analyze(void* state, char* file, double rootFrequency) -{ - loris2hise::LorisState::resetState(state); - - auto typed = (loris2hise::LorisState*)state; - - juce::File f(file); - - return typed->analyse(f, rootFrequency); -} - -bool loris_process(void* state, const char* file, const char* command, const char* json) -{ - loris2hise::LorisState::resetState(state); - - auto data = juce::JSON::fromString(juce::StringRef(json)); - - if (auto s = getExisting(state, file)) - { - try - { - return s->process(juce::Identifier(command), data); - } - catch (juce::Result& r) - { - auto m = r.getErrorMessage(); - - ((loris2hise::LorisState*)state)->reportError(m.getCharPointer().getAddress()); - } - } - - return false; -} - -bool loris_process_custom(void* state, const char* file, void* obj, void* function) -{ - loris2hise::CustomFunctionArgs::Function f = (loris2hise::CustomFunctionArgs::FunctionType)function; - - loris2hise::LorisState::resetState(state); - - if (auto s = getExisting(state, file)) - { - return s->processCustom(obj, f); - } - - return false; -} - -bool loris_set(void* state, const char* setting, const char* value) -{ - loris2hise::LorisState::resetState(state); - - auto typed = (loris2hise::LorisState*)state; - - juce::String v(value); - - return typed->setOption(juce::Identifier(setting), juce::var(v)); -} - -double loris_get(void* state, const char* setting) -{ - loris2hise::LorisState::resetState(state); - - auto typed = (loris2hise::LorisState*)state; - - return typed->getOption(juce::Identifier(setting)); -} - - -bool loris_synthesize(void* state, const char* file, float* dst, int& numChannels, int& numSamples) -{ - loris2hise::LorisState::resetState(state); - - numSamples = 0; - numChannels = 0; - - if (auto s = getExisting(state, file)) - { - jassert(s->getRequiredBytes() > 0); - - auto buffer = s->synthesize(); - - for (int i = 0; i < buffer.getNumChannels(); i++) - { - juce::FloatVectorOperations::copy(dst, buffer.getReadPointer(i), buffer.getNumSamples()); - - dst += buffer.getNumSamples(); - } - - numSamples = s->getNumSamples(); - numChannels = s->getNumChannels(); - - return true; - } - - return false; -} - -bool loris_create_envelope(void* state, const char* file, const char* parameter, int label, float* dst, int& numChannels, int& numSamples) -{ - loris2hise::LorisState::resetState(state); - - numSamples = 0; - numChannels = 0; - - if (auto s = getExisting(state, file)) - { - jassert(s->getRequiredBytes() > 0); - - auto buffer = s->renderEnvelope(juce::Identifier(parameter), label); - - for (int i = 0; i < buffer.getNumChannels(); i++) - { - juce::FloatVectorOperations::copy(dst, buffer.getReadPointer(i), buffer.getNumSamples()); - dst += buffer.getNumSamples(); - } - - numSamples = s->getNumSamples(); - numChannels = s->getNumChannels(); - - return true; - } - - return false; - -} - -bool loris_snapshot(void* state, const char* file, double time, const char* parameter, double* buffer, int& numChannels, int& numHarmonics) -{ - loris2hise::LorisState::resetState(state); - - numChannels = 0; - numHarmonics = 0; - - if (auto s = getExisting(state, file)) - { - jassert(s->getRequiredBytes() > 0); - - juce::Identifier id(parameter); - - return s->createSnapshot(id, time, buffer, numChannels, numHarmonics); - } - - return false; -} - -bool loris_prepare(void* state, const char* file, bool removeUnlabeled) -{ - loris2hise::LorisState::resetState(state); - - if (auto s = getExisting(state, file)) - { - s->prepareToMorph(removeUnlabeled); - return true; - } - - return false; -} - -bool getLastMessage(void* state, char* buffer, int maxlen) -{ - auto typed = ((loris2hise::LorisState*)state); - - auto lastMessage = typed->getLastMessage(); - - if (lastMessage.isNotEmpty()) - { - memset(buffer, 0, maxlen); - memcpy(buffer, lastMessage.getCharPointer().getAddress(), lastMessage.length()); - - return true; - } - - return false; -} - -void getIdList(char* buffer, int maxlen, bool getOptions) -{ - juce::String allCommands; - - auto idList = getOptions ? loris2hise::OptionIds::getAllIds() : loris2hise::ProcessIds::getAllIds(); - - for (const auto& id : idList) - allCommands << id.toString() << ";"; - - memset(buffer, 0, maxlen); - - memcpy(buffer, allCommands.getCharPointer().getAddress(), allCommands.length()); -} - -const char* getLastError(void* state) -{ - auto typed = ((loris2hise::LorisState*)state); - return typed->getLastError(); -} - -} - -DLL_EXPORT void setThreadController(void* state, void* t) -{ - if (auto typed = ((loris2hise::LorisState*)state)) - { - if(auto tc = static_cast(t)) - typed->setThreadController(tc); - } -} diff --git a/loris_library/Source/public.h b/loris_library/Source/public.h deleted file mode 100644 index 431fd21..0000000 --- a/loris_library/Source/public.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * This file is part of the HISE loris_library codebase (https://github.com/christophhart/loris-tools). - * Copyright (c) 2023 Christoph Hart - * - * 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, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// This file contains the public function API for calling into the dynamic library -// It's implemented as pure C API to avoid the usual C++ hassles - -#include - -#if JUCE_WINDOWS -#define DLL_EXPORT __declspec(dllexport) -#else -#define DLL_EXPORT __attribute__((visibility("default"))) -#endif - -extern "C" { - -/** Creates a new instance of a loris state that holds all analysed files. - - While it's theoretically possible to use multiple instances, it's not recommended - as there are a few functions (mainly logging) that rely on the internal loris - logging functions which use a global state. - - Returns an opaque pointer that you need to pass into all other functions. - - Call destroyLorisState to deallocate it when you're done. -*/ -DLL_EXPORT void* createLorisState(); - -/** Deallocates the state provided by createLorisState(). */ -DLL_EXPORT void destroyLorisState(void* stateToDestroy); - -/** Returns the Library version to check for mismatches. */ -DLL_EXPORT const char* getLibraryVersion(); - -/** Returns the Loris version. */ -DLL_EXPORT const char* getLorisVersion(); - - -/** Analyses the given file with the given root frequency. You need to call this method before processing and synthesizing. - - - state the state context created with createLorisState(). - - file the full path name - - rootFrequency - the estimated frequency of the samples. This will be used for setting the frequency resolution and frequency drift - - Depending on the `enablecache` optiion, the analysed partials will be cached and reused when the function is called again - with the same filename. -*/ -DLL_EXPORT bool loris_analyze(void* state, char* file, double rootFrequency); - -/** Processes the analyzed partials with a predefined function. - - - state: the state context pointer - - file: the full path name - - command: the function you want to execute. - - For an overview of the available functions and JSON configuration take a look at ScopedPartialList::process. -*/ -DLL_EXPORT bool loris_process(void* state, const char* file, - const char* command, const char* json); - -/** Processes the analyzed partials with a custom function. */ -DLL_EXPORT bool loris_process_custom(void* state, const char* file, void* obj, void* function); - -DLL_EXPORT bool loris_set(void* state, const char* setting, const char* value); - -DLL_EXPORT double loris_get(void* state, const char* setting); - -/** Returns the number of bytes that you need to allocate before calling loris_synthesize or loris_create_envelope. */ -DLL_EXPORT size_t getRequiredBytes(void* state, const char* file); - -/** Synthesises the partial list for the given file. - - state - the state context - file - the full path name - dst - a preallocated buffer that will be written to as float array. Use getRequiredBytes - in order to obtain the size of the buffer. - numChannels - will be set to the number of channels - numSamples - will be set to the number of samples -*/ -DLL_EXPORT bool loris_synthesize(void* state, const char* file, float* dst, int& numChannels, int& numSamples); - -/** Creates a audio-rate envelope for each channel of the given parameter (bandwidth, phase, frequency, amp) for the given file. - - If you've channelized the file, you can also pass in "parameter[idx]" to get the envelope for the given harmonic for the given index. */ -DLL_EXPORT bool loris_create_envelope(void* state, const char* file, const char* parameter, int label, float* dst, int& numChannels, int& numSamples); - -/** Creates a snapshot (=list of values for all partials) of the given parameter at the given time. - - Useful for creating wavetables from the analysed data. -*/ -DLL_EXPORT bool loris_snapshot(void* state, const char* file, double time, const char* parameter, double* buffer, int& numChannels, int& numHarmonics); - -/** Prepares an audio file for morphing. If removeUnlabeled is true, then all non-labeled partials will be removed. */ -DLL_EXPORT bool loris_prepare(void* state, const char* file, bool removeUnlabeled); - -DLL_EXPORT bool getLastMessage(void* state, char* buffer, int maxlen); - -DLL_EXPORT void getIdList(char* buffer, int maxlen, bool getOptions); - -DLL_EXPORT const char* getLastError(void* state); - -DLL_EXPORT void setThreadController(void* state, void* t); - - -} // extern "C" diff --git a/loris_library/Source/src/AiffData.cpp b/loris_library/Source/src/AiffData.cpp deleted file mode 100644 index 6feabbf..0000000 --- a/loris_library/Source/src/AiffData.cpp +++ /dev/null @@ -1,952 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * AiffData.C - * - * Implementation of import and export functions. - * - * Kelly Fitz, 17 Sept 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "AiffData.h" - -#include "BigEndian.h" -#include "LorisExceptions.h" -#include "Marker.h" -#include "Notifier.h" - -#include -#include -#include -#include - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// extended80 -// --------------------------------------------------------------------------- -// IEEE floating point conversions, functions defined at end of file -// (used to be in a separate file, but they aren't used anywhere else). -// - -/* struct extended80 defined below */ -struct extended80; - -/* conversion functions */ -extern void ConvertToIeeeExtended(double num, extended80 * x) ; -extern double ConvertFromIeeeExtended(const extended80 * x) ; - -/* struct extended80 definition, with - constructors and conversion to double - */ -struct extended80 -{ - char data[10]; - - extended80( double x = 0. ) { ConvertToIeeeExtended( x, this ); } - operator double( void ) const { return ConvertFromIeeeExtended( this ); } -}; - -// -- AIFF import -- - -// --------------------------------------------------------------------------- -// readChunkHeader -// --------------------------------------------------------------------------- -// Read the id and chunk size from the current file position. -// -std::istream & -readChunkHeader( std::istream & s, CkHeader & h ) -{ - ID id = 0; - Uint_32 sz = 0; - BigEndian::read( s, 1, sizeof(ID), (char *)&id ); - BigEndian::read( s, 1, sizeof(Uint_32), (char *)&sz ); - - if ( s ) - { - h.id = id; - h.size = sz; - } - - return s; -} - -// --------------------------------------------------------------------------- -// readApplicationSpecifcData -// --------------------------------------------------------------------------- -// Read the data in the ApplicationSpecific chunk, assume the stream is -// correctly positioned, and that the chunk header has already been read. -// -// Look for data specific to SPC files. Any other kind of Application -// Specific data is ignored. -// -std::istream & -readApplicationSpecifcData( std::istream & s, SosEnvelopesCk & ck, unsigned long chunkSize ) -{ - Int_32 tmp_signature; - BigEndian::read( s, 1, sizeof(Int_32), (char *)&tmp_signature ); - - if ( tmp_signature == SosEnvelopesId ) - { - ck.header.id = ApplicationSpecificId; - ck.header.size = chunkSize; - ck.signature = SosEnvelopesId; - - // lookout! The format of this chunk is a mess, due - // to obsolete stuff lying around! - BigEndian::read( s, 1, sizeof(Int_32), (char *)&ck.enhanced ); - BigEndian::read( s, 1, sizeof(Int_32), (char *)&ck.validPartials ); - s.ignore( ck.validPartials * sizeof(Int_32) ); - BigEndian::read( s, 1, sizeof(Int_32), (char *)&ck.resolution ); - s.ignore( chunkSize - (4 + ck.validPartials) * sizeof(Int_32) ); - } - else - { - s.ignore( chunkSize - sizeof(Int_32) ); - } - - if ( !s ) - { - Throw( FileIOException, "Failed to read badly-formatted AIFF file (bad ApplicationSpecific chunk)." ); - } - - return s; -} - -// --------------------------------------------------------------------------- -// readCommonData -// --------------------------------------------------------------------------- -// Read the data in the Common chunk, assume the stream is correctly -// positioned, and that the chunk header has already been read. -// -std::istream & -readCommonData( std::istream & s, CommonCk & ck, unsigned long chunkSize ) -{ - BigEndian::read( s, 1, sizeof(Int_16), (char *)&ck.channels ); - BigEndian::read( s, 1, sizeof(Int_32), (char *)&ck.sampleFrames ); - BigEndian::read( s, 1, sizeof(Int_16), (char *)&ck.bitsPerSample ); - - if ( !s ) - { - Throw( FileIOException, "Failed to read badly-formatted AIFF file (bad Common chunk)." ); - } - - ck.header.id = CommonId; - ck.header.size = chunkSize; - - // don't let this get byte-reversed: - extended80 read_rate; - BigEndian::read( s, sizeof(extended80), sizeof(char), (char *)&read_rate ); - ck.srate = read_rate; - - return s; -} - -// --------------------------------------------------------------------------- -// readContainer -// --------------------------------------------------------------------------- -// -std::istream & -readContainer( std::istream & s, ContainerCk & ck, unsigned long chunkSize ) -{ - ck.header.id = ContainerId; - ck.header.size = chunkSize; - - // read in the chunk data: - BigEndian::read( s, 1, sizeof(ID), (char *)&ck.formType ); - if ( !s ) - { - Throw( FileIOException, "Failed to read badly-formatted AIFF file (bad Container chunk)." ); - } - - // make sure its really AIFF: - if ( ck.formType != AiffType ) - { - std::string err("Bad form type in AIFF file: "); - err += std::string( ck.formType, 4 ); - Throw( FileIOException, err ); - } - - return s; -} - -// --------------------------------------------------------------------------- -// readInstrumentData -// --------------------------------------------------------------------------- -// -std::istream & -readInstrumentData( std::istream & s, InstrumentCk & ck, unsigned long chunkSize ) -{ - ck.header.id = InstrumentId; - ck.header.size = chunkSize; - - BigEndian::read( s, 1, sizeof(Byte), (char *)&ck.baseNote ); - BigEndian::read( s, 1, sizeof(Byte), (char *)&ck.detune ); - BigEndian::read( s, 1, sizeof(Byte), (char *)&ck.lowNote ); - BigEndian::read( s, 1, sizeof(Byte), (char *)&ck.highNote ); - BigEndian::read( s, 1, sizeof(Byte), (char *)&ck.lowVelocity ); - BigEndian::read( s, 1, sizeof(Byte), (char *)&ck.highVelocity ); - BigEndian::read( s, 1, sizeof(Int_16), (char *)&ck.gain ); - - // AIFFLoop is three Int_16s: - BigEndian::read( s, 1, sizeof(Uint_16), (char *)&ck.sustainLoop.playMode ); - BigEndian::read( s, 1, sizeof(Int_16), (char *)&ck.sustainLoop.beginLoop ); - BigEndian::read( s, 1, sizeof(Int_16), (char *)&ck.sustainLoop.endLoop ); - - BigEndian::read( s, 1, sizeof(Uint_16), (char *)&ck.releaseLoop.playMode ); - BigEndian::read( s, 1, sizeof(Int_16), (char *)&ck.releaseLoop.beginLoop ); - BigEndian::read( s, 1, sizeof(Int_16), (char *)&ck.releaseLoop.endLoop ); - - if ( !s ) - { - Throw( FileIOException, "Failed to read badly-formatted AIFF file (bad Common chunk)." ); - } - - return s; -} - -// --------------------------------------------------------------------------- -// readMarkerData -// --------------------------------------------------------------------------- -// -std::istream & -readMarkerData( std::istream & s, MarkerCk & ck, unsigned long chunkSize ) -{ - ck.header.id = MarkerId; - ck.header.size = chunkSize; - - Uint_32 bytesToRead = chunkSize; - - // read in the number of Markers - BigEndian::read( s, 1, sizeof(Uint_16), (char *)&ck.numMarkers ); - bytesToRead -= sizeof(Uint_16); - - for ( int i = 0; i < ck.numMarkers; ++i ) - { - MarkerCk::Marker marker; - BigEndian::read( s, 1, sizeof(Uint_16), (char *)&marker.markerID ); - bytesToRead -= sizeof(Uint_16); - - BigEndian::read( s, 1, sizeof(Uint_32), (char *)&marker.position ); - bytesToRead -= sizeof(Uint_32); - - // read the size of the name string, then the characters: - unsigned char namelength; - BigEndian::read( s, 1, sizeof(unsigned char), (char *)&namelength ); - bytesToRead -= sizeof(unsigned char); - - // need to add one to the length, because, like C-strings, - // Pascal strings are null-terminated, but the null character - // is _not_ counted in the length. - // - // Correction? At least one web source says that Pascal strings - // are _not_ null terminated, but are padded (with an extra byte - // that is not part of the count) if necessary to make the total - // number of bytes even (that is, the char bytes, _plus_ the count). - // - // This way seems to work with all the files I have tried (Kyma and - // Peak, mostly) for AIFF and Spc. - int ncharbytes = namelength; - if ( ncharbytes%2 == 0 ) - ++ncharbytes; - static char tmpChars[256]; - BigEndian::read( s, ncharbytes, sizeof(char), tmpChars ); - bytesToRead -= ncharbytes * sizeof(char); - tmpChars[ namelength ] = '\0'; - - // convert to a string: - marker.markerName = std::string( tmpChars ); - - ck.markers.push_back( marker ); - } - - if ( bytesToRead > 0 ) - { - s.ignore( bytesToRead ); - } - - if ( !s ) - { - Throw( FileIOException, "Failed to read badly-formatted AIFF file (bad Marker chunk)." ); - } - - return s; -} - -// --------------------------------------------------------------------------- -// readSamples -// --------------------------------------------------------------------------- -// Let exceptions propogate. -// -static std::istream & -readSamples( std::istream & s, std::vector< Byte > & bytes ) -{ - debugger << "reading " << bytes.size() << " bytes of sample data" << endl; - - // read integer samples without byte swapping: - BigEndian::read( s, bytes.size(), 1, (char*)(&bytes[0]) ); - - return s; -} - -// --------------------------------------------------------------------------- -// readSampleData -// --------------------------------------------------------------------------- -// Read the data in the Sound Data chunk, assume the stream is correctly -// positioned, and that the chunk header has already been read. -// -std::istream & -readSampleData( std::istream & s, SoundDataCk & ck, unsigned long chunkSize ) -{ - ck.header.id = SoundDataId; - ck.header.size = chunkSize; - - BigEndian::read( s, 1, sizeof(Uint_32), (char *)&ck.offset ); - BigEndian::read( s, 1, sizeof(Uint_32), (char *)&ck.blockSize ); - - // compute the actual number of bytes that - // can be read from this chunk: - // (chunkSize is everything after the header) - const unsigned long howManyBytes = - ( chunkSize - ck.offset ) - (2 * sizeof(Uint_32)); - - ck.sampleBytes.resize( howManyBytes, 0 ); // could throw bad_alloc - - // skip ahead to the samples and read them: - s.ignore( ck.offset ); - readSamples( s, ck.sampleBytes ); - - if ( !s ) - { - Throw( FileIOException, "Failed to read badly-formatted AIFF file (bad Sound Data chunk)." ); - } - - return s; -} - -// -- Chunk construction -- - -// --------------------------------------------------------------------------- -// configureCommonCk -// --------------------------------------------------------------------------- -void -configureCommonCk( CommonCk & ck, unsigned long nFrames, unsigned int nChans, - unsigned int bps, double srate ) -{ - ck.header.id = CommonId; - - // size is everything after the header: - ck.header.size = sizeof(Int_16) + // num channels - sizeof(Int_32) + // num frames - sizeof(Int_16) + // bits per sample - sizeof(extended80); // sample rate - - ck.channels = nChans; - ck.sampleFrames = nFrames; - ck.bitsPerSample = bps; - ck.srate = srate; - // ConvertToIeeeExtended( srate, &ck.srate ); - -} - -// --------------------------------------------------------------------------- -// configureContainer -// --------------------------------------------------------------------------- -// dataSize is the combined size of all other chunks in file. Configure -// them first, then add their sizes (with headers!). -// -void -configureContainer( ContainerCk & ck, unsigned long dataSize ) -{ - ck.header.id = ContainerId; - - // size is everything after the header: - ck.header.size = sizeof(Int_32) + dataSize; - - ck.formType = AiffType; -} - -// --------------------------------------------------------------------------- -// configureInstrumentCk -// --------------------------------------------------------------------------- -void -configureInstrumentCk( InstrumentCk & ck, double midiNoteNum ) -{ - ck.header.id = InstrumentId; - - // size is everything after the header: - ck.header.size = - sizeof(Byte) + // baseFrequency - sizeof(Byte) + // detune - sizeof(Byte) + // lowFrequency - sizeof(Byte) + // highFrequency - sizeof(Byte) + // lowVelocity - sizeof(Byte) + // highVelocity - sizeof(Int_16) + // gain - 2 * sizeof(Int_16) + // playmode for sustainLoop and releaseLoop - 2 * sizeof(Uint_16) + // beginLoop for sustainLoop and releaseLoop - 2 * sizeof(Uint_16); // loopEnd for sustainLoop and releaseLoop - - ck.baseNote = Byte( midiNoteNum ); - ck.detune = Byte(long( 100 * midiNoteNum ) % 100); - if (ck.detune > 50) - { - ck.baseNote++; - ck.detune -= 100; - } - ck.detune *= -1; - - ck.lowNote = 0; - ck.highNote = 127; - ck.lowVelocity = 1; - ck.highVelocity = 127; - ck.gain = 0; - ck.sustainLoop.playMode = 0; // Sustain looping done by name, not by this - ck.sustainLoop.beginLoop = 0; - ck.sustainLoop.endLoop = 0; - ck.releaseLoop.playMode = 0; // No Looping - ck.releaseLoop.beginLoop = 0; - ck.releaseLoop.endLoop = 0; -} - -// --------------------------------------------------------------------------- -// configureMarkerCk -// --------------------------------------------------------------------------- -void -configureMarkerCk( MarkerCk & ck, const std::vector< Marker > & markers, double srate ) -{ - ck.header.id = MarkerId; - - // accumulate data size - Uint_32 dataSize = sizeof(Uint_16); // num markers - - ck.numMarkers = markers.size(); - ck.markers.resize( markers.size() ); - for ( unsigned int j = 0; j < markers.size(); ++j ) - { - MarkerCk::Marker & m = ck.markers[j]; - m.markerID = j+1; - m.position = Uint_32((markers[j].time() * srate) + 0.5); - m.markerName = markers[j].name(); - - #define MAX_PSTRING_CHARS 254 - if ( m.markerName.size() > MAX_PSTRING_CHARS ) - m.markerName.resize( MAX_PSTRING_CHARS ); - - // the size of a pascal string is the number of - // characters plus the size byte, plus the terminal '\0'. - // - // Actualy, at least one web source indicates that Pascal - // strings are not null-terminated, but that they _are_ - // padded with an extra (not part of the count) byte - // if necessary to ensure that the total length (including - // count) is even, and this seems to work better with other - // programs (e.g. Kyma) - if ( m.markerName.size()%2 == 0 ) - m.markerName += '\0'; - dataSize += sizeof(Uint_16) + sizeof(Uint_32) + (m.markerName.size() + 1); - } - - // must be an even number of bytes - if ( dataSize%2 ) - ++dataSize; - - ck.header.size = dataSize; -} - -// --------------------------------------------------------------------------- -// configureSoundDataCk -// --------------------------------------------------------------------------- -// -void -configureSoundDataCk( SoundDataCk & ck, const std::vector< double > & samples, - unsigned int bps ) -{ - Uint_32 dataSize = samples.size() * (bps/8); - // must be an even number of bytes: - if ( dataSize % 2 ) - { - ++dataSize; - } - - ck.header.id = SoundDataId; - - // size is everything after the header: - ck.header.size = sizeof(Uint_32) + // offset - sizeof(Uint_32) + // block size - dataSize; // sample data - - - // no block alignment: - ck.offset = 0; - ck.blockSize = 0; - - // convert the samples to integers stored in - // big endian order in the byte vector: - convertSamplesToBytes( samples, ck.sampleBytes, bps ); -} - - -// -- AIFF export -- - -// --------------------------------------------------------------------------- -// writeCommon -// --------------------------------------------------------------------------- -// -std::ostream & -writeCommonData( std::ostream & s, const CommonCk & ck ) -{ -/* - debugger << "writing common chunk: " << endl; - debugger << "header id: " << ck.header.id << endl; - debugger << "size: " << ck.header.size << endl; - debugger << "channels: " << ck.channels << endl; - debugger << "sample frames: " << ck.sampleFrames << endl; - debugger << "bits per sample: " << ck.bitsPerSample << endl; - //debugger << "rate: " << _sampleRate << endl; -*/ - - // write it out: - try - { - BigEndian::write( s, 1, sizeof(ID), (char *)&ck.header.id ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.header.size ); - BigEndian::write( s, 1, sizeof(Int_16), (char *)&ck.channels ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.sampleFrames ); - BigEndian::write( s, 1, sizeof(Int_16), (char *)&ck.bitsPerSample ); - // don't let this get byte-reversed: - extended80 write_rate( ck.srate ); - //ConvertToIeeeExtended( &ck.srate, write_rate ); - - BigEndian::write( s, sizeof(extended80), sizeof(char), (char *)&write_rate ); - } - catch( FileIOException & ex ) - { - ex.append( "Failed to write AIFF file Common chunk." ); - throw; - } - - return s; -} - -// --------------------------------------------------------------------------- -// writeContainer -// --------------------------------------------------------------------------- -// -std::ostream & -writeContainer( std::ostream & s, const ContainerCk & ck ) -{ -/* - debugger << "writing container: " << endl; - debugger << "header id: " << ck.header.id << endl; - debugger << "size: " << ck.header.size << endl; - debugger << "type: " << ck.formType << endl; -*/ - - // write it out: - try - { - BigEndian::write( s, 1, sizeof(ID), (char *)&ck.header.id ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.header.size ); - BigEndian::write( s, 1, sizeof(ID), (char *)&ck.formType ); - } - catch( FileIOException & ex ) - { - ex.append( "Failed to write AIFF file Container chunk." ); - throw; - } - - return s; -} - -// --------------------------------------------------------------------------- -// writeInstrumentData -// --------------------------------------------------------------------------- -std::ostream & -writeInstrumentData( std::ostream & s, const InstrumentCk & ck ) -{ - try - { - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.header.id ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.header.size ); - - BigEndian::write( s, 1, sizeof(Byte), (char *)&ck.baseNote ); - BigEndian::write( s, 1, sizeof(Byte), (char *)&ck.detune ); - BigEndian::write( s, 1, sizeof(Byte), (char *)&ck.lowNote ); - BigEndian::write( s, 1, sizeof(Byte), (char *)&ck.highNote ); - BigEndian::write( s, 1, sizeof(Byte), (char *)&ck.lowVelocity ); - BigEndian::write( s, 1, sizeof(Byte), (char *)&ck.highVelocity ); - BigEndian::write( s, 1, sizeof(Int_16), (char *)&ck.gain ); - - // AIFFLoop is three Int_16s: - BigEndian::write( s, 3, sizeof(Int_16), (char *)&ck.sustainLoop ); - BigEndian::write( s, 3, sizeof(Int_16), (char *)&ck.releaseLoop ); - } - catch( FileIOException & ex ) - { - ex.append( " Failed to write SPC file Instrument chunk." ); - throw; - } - - return s; -} - -// --------------------------------------------------------------------------- -// writeMarkerData -// --------------------------------------------------------------------------- -std::ostream & -writeMarkerData( std::ostream & s, const MarkerCk & ck ) -{ - try - { - BigEndian::write( s, 1, sizeof(ID), (char *)&ck.header.id ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.header.size ); - BigEndian::write( s, 1, sizeof(Uint_16), (char *)&ck.numMarkers ); - - int markerbytes = 0; - for ( unsigned int j = 0; j < ck.markers.size(); ++j ) - { - const MarkerCk::Marker & m = ck.markers[j]; - BigEndian::write( s, 1, sizeof(Uint_16), (char *)&m.markerID ); - BigEndian::write( s, 1, sizeof(Uint_32), (char *)&m.position ); - - // the size of a pascal string is the number of - // characters plus the size byte, plus the terminal '\0': - // Actualy, at least one web source indicates that Pascal - // strings are not null-terminated, but that they _are_ - // padded with an extra (not part of the count) byte - // if necessary to ensure that the total length (including - // count) is even, and this seems to work better with other - // programs (e.g. Kyma) - Uint_32 bytesToWrite = (m.markerName.size() + 1) * sizeof(char); - - // format pascal string: - static char tmpChars[256]; - tmpChars[0] = m.markerName.size(); - std::copy( m.markerName.begin(), m.markerName.end(), tmpChars + 1 ); - tmpChars[m.markerName.size()+1] = '\0'; - - BigEndian::write( s, bytesToWrite, sizeof(char), tmpChars ); - markerbytes += bytesToWrite; - } - - // be sure to write an even number of bytes - if ( markerbytes%2 ) - BigEndian::write( s, 1, sizeof(char), "\0" ); - - } - catch( FileIOException & ex ) - { - ex.append( "Failed to write AIFF file Marker chunk." ); - throw; - } - - return s; -} - -// --------------------------------------------------------------------------- -// writeSamples -// --------------------------------------------------------------------------- -// Let exceptions propogate. -// -static std::ostream & -writeSamples( std::ostream & s, const std::vector< Byte > & bytes ) -{ -// debugger << "writing " << bytes.size() << " bytes of sample data" << endl; - - // write integer samples without byte swapping, - // the bytes were constructed in the correct - // big endian order (see convertSamplesToBytes): - BigEndian::write( s, bytes.size(), 1, (char*)(&bytes[0]) ); - - return s; -} - -// --------------------------------------------------------------------------- -// writeSampleData -// --------------------------------------------------------------------------- -// -std::ostream & -writeSampleData( std::ostream & s, const SoundDataCk & ck ) -{ -/* - debugger << "writing sample data: " << endl; - debugger << "header id: " << ck.header.id << endl; - debugger << "size: " << ck.header.size << endl; - debugger << "offset: " << ck.offset << endl; - debugger << "block size: " << ck.blockSize << endl; -*/ - - // write it out: - try - { - BigEndian::write( s, 1, sizeof(ID), (char *)&ck.header.id ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.header.size ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.offset ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.blockSize ); - - writeSamples( s, ck.sampleBytes ); - } - catch( FileIOException & ex ) - { - ex.append( "Failed to write AIFF file Container chunk." ); - throw; - } - - return s; -} - -// -- sample conversion -- - -// --------------------------------------------------------------------------- -// convertBytesToSamples -// --------------------------------------------------------------------------- -// Convert sample bytes to double precision floating point samples -// (-1.0, 1.0). The samples vector is resized to fit exactly as many -// samples as are represented in the bytes vector, and any prior -// contents are overwritten. -// -void -convertBytesToSamples( const std::vector< Byte > & bytes, - std::vector< double > & samples, unsigned int bps ) -{ - Assert( bps <= 32 ); - - typedef std::vector< double >::size_type size_type; - - const int bytesPerSample = bps / 8; - samples.resize( bytes.size() / bytesPerSample ); - - debugger << "converting " << samples.size() << " samples of size " - << bps << " bits" << endl; - - // shift sample bytes into a long integer, and - // scale to make a double: - const double oneOverMax = std::pow(0.5, double(bps-1)); - long samp; - - std::vector< Byte >::const_iterator bytePos = bytes.begin(); - std::vector< double >::iterator samplePos = samples.begin(); - while ( samplePos != samples.end() ) - { - // assign the leading byte, so that the sign - // is preserved: - samp = static_cast(*(bytePos++)); - for ( size_type j = 1; j < bytesPerSample; ++j ) - { - Assert( bytePos != bytes.end() ); - - // OR bytes after the most significant, so - // that their sign is ignored: - samp = (samp << 8) + (unsigned char)*(bytePos++); - - // cannot decide why this didn't work, - // instead of the add above. - //samp |= (unsigned long)*(bytePos++); - } - - *(samplePos++) = oneOverMax * samp; - } -} - -// --------------------------------------------------------------------------- -// convertSamplesToBytes -// --------------------------------------------------------------------------- -// Convert floating point samples (-1.0, 1.0) to bytes. -// The bytes vector is resized to fit exactly as many -// samples as are stored in the samples vector, and any prior -// contents are overwritten. -// -// This formats the samples as big endian bytes, that is, the most -// significant bytes are stored earlier in the byte vector, so -// no byte-swapping should be performed when this byte array is -// written to disk, and moreover this function is specific to -// big-endian data storage (like AIFF files). -void -convertSamplesToBytes( const std::vector< double > & samples, - std::vector< Byte > & bytes, unsigned int bps ) -{ - Assert( bps <= 32 ); - - typedef std::vector< Byte >::size_type size_type; - - // grow the bytes vector, must be an even number - // of bytes: - const int bytesPerSample = bps / 8; - size_type howManyBytes = samples.size() * bytesPerSample; - if ( howManyBytes%2 ) - ++howManyBytes; - bytes.resize( howManyBytes ); - - debugger << "converting " << samples.size() << " samples to size " - << bps << " bits" << endl; - - // shift sample bytes into a long integer, and - // scale to make a double: - const double maxSample = std::pow(2., double(bps-1)); - long samp; - - std::vector< Byte >::iterator bytePos = bytes.begin(); - std::vector< double >::const_iterator samplePos = samples.begin(); - while ( samplePos != samples.end() ) - { - samp = long(*(samplePos++) * maxSample); - - // store the sample bytes in big endian order, - // most significant byte first: - for ( size_type j = bytesPerSample; j > 0; --j ) - { - //Assert( bytePos != bytes.end() ); - // mask the lowest byte after shifting: - *(bytePos++) = 0xFF & (samp >> (8*(j-1))); - } - } -} - -// --------------------------------------------------------------------------- -// extended80 -// --------------------------------------------------------------------------- -// IEEE floating point conversions. -// - -#ifndef HUGE_VAL -# define HUGE_VAL HUGE -#endif /* HUGE_VAL */ - -#define FloatToUnsigned(f)((Int_32)((Int_32(f - 2147483648.0)) + (Int_32)(2147483647)) + 1) - -void ConvertToIeeeExtended(double num, extended80 * x) -{ - int sign; - int expon; - double fMant, fsMant; - Int_32 hiMant, loMant; - char * bytes = x->data; - - if (num < 0) { - sign = 0x8000; - num *= -1; - } else - sign = 0; - - if (num == 0) { - expon = 0; - hiMant = 0; - loMant = 0; - } else { - fMant = frexp(num, &expon); - if ((expon > 16384) || !(fMant < 1)) { /* Infinity or NaN */ - expon = sign | 0x7FFF; - hiMant = 0; - loMant = 0; - } - /* infinity */ - else { /* Finite */ - expon += 16382; - if (expon < 0) { /* denormalized */ - fMant = ldexp(fMant, expon); - expon = 0; - } - expon |= sign; - fMant = ldexp(fMant, 32); - fsMant = floor(fMant); - hiMant = FloatToUnsigned(fsMant); - fMant = ldexp(fMant - fsMant, 32); - fsMant = floor(fMant); - loMant = FloatToUnsigned(fsMant); - } - } - - bytes[0] = expon >> 8; - bytes[1] = expon; - - bytes[2] = hiMant >> 24; - bytes[3] = hiMant >> 16; - bytes[4] = hiMant >> 8; - bytes[5] = hiMant; - - bytes[6] = loMant >> 24; - bytes[7] = loMant >> 16; - bytes[8] = loMant >> 8; - bytes[9] = loMant; - -} - -#ifndef HUGE_VAL -# define HUGE_VAL HUGE -#endif /* HUGE_VAL */ - -# define UnsignedToFloat(u)(((double)((Int_32)(u - (Int_32)(2147483647) - 1))) + 2147483648.0) - -/**************************************************************** - * Extended precision IEEE floating-point conversion routine. - ****************************************************************/ - -double ConvertFromIeeeExtended(const extended80 * x) -{ /* LCN */ /* ? */ - double f; - int expon; - Int_32 hiMant, loMant; - const char * bytes = x->data; - - expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF); - hiMant = ((int)(bytes[2] & 0xFF) << 24) - | ((int)(bytes[3] & 0xFF) << 16) - | ((int)(bytes[4] & 0xFF) << 8) - | ((int)(bytes[5] & 0xFF)); - loMant = ((int)(bytes[6] & 0xFF) << 24) - | ((int)(bytes[7] & 0xFF) << 16) - | ((int)(bytes[8] & 0xFF) << 8) - | ((int)(bytes[9] & 0xFF)); - - if (expon == 0 && hiMant == 0 && loMant == 0) - f = 0; - else { - if (expon == 0x7FFF) /* Infinity or NaN */ - f = HUGE_VAL; - else { - expon -= 16383; - f = ldexp(UnsignedToFloat(hiMant), expon -= 31); - f += ldexp(UnsignedToFloat(loMant), expon -= 32); - } - } - - if (bytes[0] & 0x80) - { - f = -f; - } - - return f; -} - - -} // end of namespace Loris diff --git a/loris_library/Source/src/AiffData.h b/loris_library/Source/src/AiffData.h deleted file mode 100644 index fb07ed2..0000000 --- a/loris_library/Source/src/AiffData.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * AiffData.h - * - * Declarations of import and export functions. - * - * Kelly Fitz, 17 Sept 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Marker.h" - -#include -#include - -// in case configure wasn't run (no config.h), -// pick some (hopefully-) reasonable values for -// these things and hope for the best... -#if ! defined( SIZEOF_SHORT ) -#define SIZEOF_SHORT 2 -#endif - -#if ! defined( SIZEOF_INT ) -#define SIZEOF_INT 4 -#endif - -#if ! defined( SIZEOF_LONG ) -#define SIZEOF_LONG 4 // not for DEC Alpha! -#endif - - -#if SIZEOF_SHORT == 2 -typedef short Int_16; -typedef unsigned short Uint_16; -#elif SIZEOF_INT == 2 -typedef int Int_16; -typedef unsigned int Uint_16; -#else -#error "cannot find an appropriate type for 16-bit integers" -#endif - -#if SIZEOF_INT == 4 -typedef int Int_32; -typedef unsigned int Uint_32; -#elif SIZEOF_LONG == 4 -typedef long Int_32; -typedef unsigned long Uint_32; -#else -#error "cannot find an appropriate type for 32-bit integers" -#endif - - -// begin namespace -namespace Loris { - -// -- chunk types -- -enum -{ - ContainerId = 0x464f524d, // 'FORM' - AiffType = 0x41494646, // 'AIFF' - CommonId = 0x434f4d4d, // 'COMM' - ApplicationSpecificId = 0x4150504c, // 'APPL' - SosEnvelopesId = 0x534f5365, // 'SOSe' - SoundDataId = 0x53534e44, // 'SSND' - InstrumentId = 0x494e5354, // 'INST' - MarkerId = 0x4d41524b // 'MARK' -}; - -typedef Uint_32 ID; -typedef char Byte; - -struct CkHeader -{ - ID id; - Uint_32 size; - - // providing this default constructor - // gives clients a way to determine whether - // a chunk has been read and assigned: - CkHeader( void ) : id(0), size(0) {} -}; - -struct ContainerCk -{ - CkHeader header; - ID formType; -}; - -struct CommonCk -{ - CkHeader header; - Int_16 channels; // number of channels - Int_32 sampleFrames; // channel independent sample frames - Int_16 bitsPerSample; // number of bits per sample - double srate; // sampling rate (stored in IEEE 10 byte format) -}; - -struct SoundDataCk -{ - CkHeader header; - Uint_32 offset; - Uint_32 blockSize; - - // sample frames follow - std::vector< Byte > sampleBytes; -}; - -struct MarkerCk -{ - CkHeader header; - Uint_16 numMarkers; - - struct Marker - { - Uint_16 markerID; - Uint_32 position; // position in uncompressed samples - std::string markerName; - }; - - std::vector< MarkerCk::Marker > markers; -}; - -struct InstrumentCk -{ - CkHeader header; - Byte baseNote; /* all notes are MIDI note numbers */ - Byte detune; /* cents off, only -50 to +50 are significant */ - Byte lowNote; - Byte highNote; - Byte lowVelocity; /* 1 to 127 */ - Byte highVelocity; /* 1 to 127 */ - Int_16 gain; /* in dB, 0 is normal */ - - struct Loop - { - Int_16 playMode; /* 0 - no loop, 1 - forward looping, 2 - backward looping */ - Uint_16 beginLoop; /* this is a reference to a markerID, so you always - ÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊ have to work with MARK and INST together!! */ - Uint_16 endLoop; - }; - - Loop sustainLoop; - Loop releaseLoop; -}; - - -struct SosEnvelopesCk -{ - CkHeader header; - Int_32 signature; // For SOS, should be 'SOSe' - Int_32 enhanced; // 0 for sine-only, 1 for bandwidth-enhanced - Int_32 validPartials; // Number of partials with data in them; the file must - // be padded out to the next higher 2**n partials; - // this number is doubled for enhanced files - - // skip validPartials * sizeof(Int_32) bytes of junk here - Int_32 resolution; // frame duration in microseconds - Int_32 quasiHarmonic; // how many of the partials are quasiharmonic - // skip - // (4*LargestLabel + 8 - validPartials - 2) * sizeof(Int_32) - // bytes of junk here - -/* - // this stuff is unbelievably nasty! - -#define initPhaseLth ( 4*LargestLabel + 8 ) - Int_32 initPhase[initPhaseLth]; // obsolete initial phase array; is VARIABLE LENGTH array - // this is big enough for a max of 512 enhanced partials plus values below -// Int_32 resolution; // frame duration in microseconds - #define SOSresolution( es ) initPhase[ spcEI.enhanced \ - ? 2 * spcEI.numPartials : spcEI.numPartials] - // follows the initPhase[] array - - -// Int_32 quasiHarmonic; // how many of the partials are quasiharmonic - #define SOSquasiHarmonic( es ) initPhase[ spcEI.enhanced \ - ? 2 * spcEI.numPartials + 1 : spcEI.numPartials + 1] - // follows the initPhase[] array -*/ -}; - -// --------------------------------------------------------------------------- -// readChunkHeader -// --------------------------------------------------------------------------- -// Read the id and chunk size from the current file position. -// Let exceptions propogate. -// -std::istream & -readChunkHeader( std::istream & s, CkHeader & h ); - - -// --------------------------------------------------------------------------- -// readApplicationSpecifcData -// --------------------------------------------------------------------------- -// Read the data in the ApplicationSpecific chunk, assume the stream is -// correctly positioned, and that the chunk header has already been read. -// -// Look for data specific to SPC files. Any other kind of Application -// Specific data is ignored. -// -std::istream & -readApplicationSpecifcData( std::istream & s, SosEnvelopesCk & ck, unsigned long chunkSize ); - - -// --------------------------------------------------------------------------- -// readCommonData -// --------------------------------------------------------------------------- -// Read the data in the Common chunk, assume the stream is correctly -// positioned, and that the chunk header has already been read. -// -std::istream & -readCommonData( std::istream & s, CommonCk & ck, unsigned long chunkSize ); - -// --------------------------------------------------------------------------- -// readContainer -// --------------------------------------------------------------------------- -// -std::istream & -readContainer( std::istream & s, ContainerCk & ck, unsigned long chunkSize ); - -// --------------------------------------------------------------------------- -// readInstrumentData -// --------------------------------------------------------------------------- -// -std::istream & -readInstrumentData( std::istream & s, InstrumentCk & ck, unsigned long chunkSize ); - -// --------------------------------------------------------------------------- -// readMarkerData -// --------------------------------------------------------------------------- -// -std::istream & -readMarkerData( std::istream & s, MarkerCk & ck, unsigned long chunkSize ); - -// --------------------------------------------------------------------------- -// readSampleData -// --------------------------------------------------------------------------- -// Read the data in the Sound Data chunk, assume the stream is correctly -// positioned, and that the chunk header has already been read. -// -std::istream & -readSampleData( std::istream & s, SoundDataCk & ck, unsigned long chunkSize ); - -// --------------------------------------------------------------------------- -// configureCommonCk -// --------------------------------------------------------------------------- -void -configureCommonCk( CommonCk & ck, unsigned long nFrames, unsigned int nChans, - unsigned int bps, double srate ); - -// --------------------------------------------------------------------------- -// configureContainer -// --------------------------------------------------------------------------- -// dataSize is the combined size of all other chunks in file. Configure -// them first, then add their sizes (with headers!). -// -void -configureContainer( ContainerCk & ck, unsigned long dataSize ); - -// --------------------------------------------------------------------------- -// configureInstrumentCk -// --------------------------------------------------------------------------- -void -configureInstrumentCk( InstrumentCk & ck, double midiNoteNum ); - -// --------------------------------------------------------------------------- -// configureMarkerCk -// --------------------------------------------------------------------------- -void -configureMarkerCk( MarkerCk & ck, const std::vector< Marker > & markers, - double srate ); - -// --------------------------------------------------------------------------- -// configureSoundDataCk -// --------------------------------------------------------------------------- -// -void -configureSoundDataCk( SoundDataCk & ck, const std::vector< double > & samples, - unsigned int bps ); - -// --------------------------------------------------------------------------- -// writeCommon -// --------------------------------------------------------------------------- -// -std::ostream & -writeCommonData( std::ostream & s, const CommonCk & ck ); - -// --------------------------------------------------------------------------- -// writeContainer -// --------------------------------------------------------------------------- -// -std::ostream & -writeContainer( std::ostream & s, const ContainerCk & ck ); - -// --------------------------------------------------------------------------- -// writeInstrumentData -// --------------------------------------------------------------------------- -std::ostream & -writeInstrumentData( std::ostream & s, const InstrumentCk & ck ); - -// --------------------------------------------------------------------------- -// writeMarkerData -// --------------------------------------------------------------------------- -std::ostream & -writeMarkerData( std::ostream & s, const MarkerCk & ck ); - -// --------------------------------------------------------------------------- -// writeSampleData -// --------------------------------------------------------------------------- -// -std::ostream & -writeSampleData( std::ostream & s, const SoundDataCk & ck ); - -// --------------------------------------------------------------------------- -// convertBytesToSamples -// --------------------------------------------------------------------------- -// Convert sample bytes to double precision floating point samples -// (-1.0, 1.0). The samples vector is resized to fit exactly as many -// samples as are represented in the bytes vector, and any prior -// contents are overwritten. -// -void -convertBytesToSamples( const std::vector< Byte > & bytes, - std::vector< double > & samples, unsigned int bps ); - -// --------------------------------------------------------------------------- -// convertSamplesToBytes -// --------------------------------------------------------------------------- -// Convert floating point samples (-1.0, 1.0) to bytes. -// The bytes vector is resized to fit exactly as many -// samples as are stored in the samples vector, and any prior -// contents are overwritten. -// -void -convertSamplesToBytes( const std::vector< double > & samples, - std::vector< Byte > & bytes, unsigned int bps ); - -} // end of namespace diff --git a/loris_library/Source/src/AiffFile.cpp b/loris_library/Source/src/AiffFile.cpp deleted file mode 100644 index a494098..0000000 --- a/loris_library/Source/src/AiffFile.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * AiffFile.C - * - * Implementation of AiffFile class for sample import and export in Loris. - * - * Class AiffFile represents sample data in a AIFF-format samples - * file, and manages file I/O and sample conversion. Since the sound - * analysis and synthesis algorithms in Loris and the reassigned - * bandwidth-enhanced representation are monaural, AiffFile manages - * only monaural (single channel) AIFF-format samples files. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "AiffFile.h" - -#include "AiffData.h" -#include "LorisExceptions.h" -#include "Marker.h" -#include "Notifier.h" -#include "Synthesizer.h" - -#include -#include -#include -#include - -// begin namespace -namespace Loris { - - -// -- construction -- - -// --------------------------------------------------------------------------- -// AiffFile constructor from filename -// --------------------------------------------------------------------------- -//! Initialize an instance of AiffFile by importing sample data from -//! the file having the specified filename or path. -//! -//! \param filename is the name or path of an AIFF samples file -// -AiffFile::AiffFile( const std::string & filename ) : - notenum_( 60 ), - rate_( 1 ), // rate will be overwritten on import - numchans_( 1 ) -{ - readAiffData( filename ); -} - -// --------------------------------------------------------------------------- -// AiffFile constructor from parameters, no samples. -// --------------------------------------------------------------------------- -//! Initialize an instance of AiffFile having the specified sample -//! rate, preallocating numFrames samples, initialized to zero. -//! -//! \param samplerate is the rate at which Partials are rendered -//! \param numFrames is the initial number of (zero) samples. If -//! unspecified, no samples are preallocated. -// -AiffFile::AiffFile( double samplerate, size_type numFrames /* = 0 */, - unsigned int numChannels /* = 1 */ ) : - notenum_( 60 ), - rate_( samplerate ), - numchans_( numChannels ), - samples_( numFrames * numChannels, 0 ) -{ -} - -// --------------------------------------------------------------------------- -// AiffFile constructor from sample data -// --------------------------------------------------------------------------- -//! Initialize an instance of AiffFile from a buffer of sample -//! data, with the specified sample rate. -//! -//! \param buffer is a pointer to a buffer of floating point samples. -//! \param bufferlength is the number of samples in the buffer. -//! \param samplerate is the sample rate of the samples in the buffer. -// -AiffFile::AiffFile( const double * buffer, size_type bufferlength, double samplerate ) : - notenum_( 60 ), - rate_( samplerate ), - numchans_( 1 ) -{ - samples_.insert( samples_.begin(), buffer, buffer+bufferlength ); -} - -// --------------------------------------------------------------------------- -// AiffFile constructor from stereo sample data -// --------------------------------------------------------------------------- -//! Initialize an instance of AiffFile from two buffers of sample -//! data, with the specified sample rate. Both buffers must store -//! the same number (bufferLength) of samples. -//! -//! \param buffer_left is a pointer to a buffer of floating point samples -//! representing the left channel samples. -//! \param buffer_right is a pointer to a buffer of floating point samples -//! representing the right channel samples. -//! \param bufferlength is the number of samples in the buffer. -//! \param samplerate is the sample rate of the samples in the buffer. -// -AiffFile::AiffFile( const double * buffer_left, const double * buffer_right, - size_type bufferlength, double samplerate ) : - notenum_( 60 ), - rate_( samplerate ), - numchans_( 2 ) -{ - // interleave the two channels in samples_ - samples_.resize( 2*bufferlength, 0. ); - size_type idx = 0; - while( idx < samples_.size() ) - { - samples_[ idx++ ] = *buffer_left++; - samples_[ idx++ ] = *buffer_right++; - } -} - -// --------------------------------------------------------------------------- -// AiffFile constructor from sample data -// --------------------------------------------------------------------------- -//! Initialize an instance of AiffFile from a vector of sample -//! data, with the specified sample rate. -//! -//! \param vec is a vector of floating point samples. -//! \param samplerate is the sample rate of the samples in the vector. -// -AiffFile::AiffFile( const std::vector< double > & vec, double samplerate ) : - notenum_( 60 ), - rate_( samplerate ), - numchans_( 1 ), - samples_( vec.begin(), vec.end() ) -{ -} - -// --------------------------------------------------------------------------- -// AiffFile constructor from stereo sample data -// --------------------------------------------------------------------------- -//! Initialize an instance of AiffFile from two vectors of sample -//! data, with the specified sample rate. If the two vectors have different -//! lengths, the shorter one is padded with zeros. -//! -//! \param vec_left is a vector of floating point samples representing the -//! left channel samples. -//! \param vec_right is a vector of floating point samples representing the -//! right channel samples. -//! \param samplerate is the sample rate of the samples in the vectors. -// -AiffFile::AiffFile( const std::vector< double > & vec_left, - const std::vector< double > & vec_right, - double samplerate ) : - notenum_( 60 ), - rate_( samplerate ), - numchans_( 2 ), - samples_( 2 * std::max( vec_left.size(), vec_right.size() ), 0. ) -{ - // interleave the two channels in samples_ - size_type idx = 0; - std::vector< double >::const_iterator iter_left = vec_left.begin(); - std::vector< double >::const_iterator iter_right= vec_right.begin(); - while( idx < samples_.size() ) - { - if ( iter_left != vec_left.end() ) - { - samples_[ idx ] = *iter_left++; - } - if ( iter_right != vec_right.end() ) - { - samples_[ idx+1 ] = *iter_right++; - } - idx += 2; - } -} - -// --------------------------------------------------------------------------- -// AiffFile copy constructor -// --------------------------------------------------------------------------- -//! Initialize this and AiffFile that is an exact copy, having -//! all the same sample data, as another AiffFile. -//! -//! \param other is the AiffFile to copy -// -AiffFile::AiffFile( const AiffFile & other ) : - notenum_( other.notenum_ ), - rate_( other.rate_ ), - numchans_( other.numchans_ ), - markers_( other.markers_ ), - samples_( other.samples_ ) -{ -} - -// --------------------------------------------------------------------------- -// AiffFile assignment operator -// --------------------------------------------------------------------------- -//! Assignment operator: change this AiffFile to be an exact copy -//! of the specified AiffFile, rhs, that is, having the same sample -//! data. -//! -//! \param rhs is the AiffFile to replicate -// -AiffFile & -AiffFile::operator= ( const AiffFile & rhs ) -{ - if ( &rhs != this ) - { - // before modifying anything, make - // sure there's enough space: - samples_.reserve( rhs.samples_.size() ); - markers_.reserve( rhs.markers_.size() ); - - notenum_ = rhs.notenum_; - rate_ = rhs.rate_; - numchans_ = rhs.numchans_; - markers_ = rhs.markers_; - samples_ = rhs.samples_; - } - return *this; -} - -// -- export -- - -// --------------------------------------------------------------------------- -// write -// --------------------------------------------------------------------------- -//! Export the sample data represented by this AiffFile to -//! the file having the specified filename or path. Export -//! signed integer samples of the specified size, in bits -//! (8, 16, 24, or 32). -//! -//! \param filename is the name or path of the AIFF samples file -//! to be created or overwritten. -//! \param bps is the number of bits per sample to store in the -//! samples file (8, 16, 24, or 32).If unspeicified, 16 bits -//! is assumed. -// -void -AiffFile::write( const std::string & filename, unsigned int bps ) -{ - static const unsigned int ValidSizes[] = { 8, 16, 24, 32 }; - if ( std::find( ValidSizes, ValidSizes+4, bps ) == ValidSizes+4 ) - { - Throw( InvalidArgument, "Invalid bits-per-sample." ); - } - - std::ofstream s( filename.c_str(), std::ofstream::binary ); - if ( ! s ) - { - std::string s = "Could not create file \""; - s += filename; - s += "\". Failed to write AIFF file."; - Throw( FileIOException, s ); - } - - unsigned long dataSize = 0; - - CommonCk commonChunk; - configureCommonCk( commonChunk, samples_.size() / numchans_, numchans_, bps, rate_ ); - dataSize += commonChunk.header.size + sizeof(CkHeader); - - SoundDataCk soundDataChunk; - configureSoundDataCk( soundDataChunk, samples_, bps ); - dataSize += soundDataChunk.header.size + sizeof(CkHeader); - - InstrumentCk instrumentChunk; - configureInstrumentCk( instrumentChunk, notenum_ ); - dataSize += instrumentChunk.header.size + sizeof(CkHeader); - - MarkerCk markerChunk; - if ( ! markers_.empty() ) - { - configureMarkerCk( markerChunk, markers_, rate_ ); - dataSize += markerChunk.header.size + sizeof(CkHeader); - } - - ContainerCk containerChunk; - configureContainer( containerChunk, dataSize ); - - try - { - writeContainer( s, containerChunk ); - writeCommonData( s, commonChunk ); - if ( ! markers_.empty() ) - writeMarkerData( s, markerChunk ); - writeInstrumentData( s, instrumentChunk ); - writeSampleData( s, soundDataChunk ); - - s.close(); - } - catch ( Exception & ex ) - { - ex.append( " Failed to write AIFF file." ); - throw; - } -} - -// -- access -- - -// --------------------------------------------------------------------------- -// markers -// --------------------------------------------------------------------------- -//! Return a reference to the Marker (see Marker.h) container -//! for this AiffFile. -// -AiffFile::markers_type & -AiffFile::markers( void ) -{ - return markers_; -} - -//! Return a const reference to the Marker (see Marker.h) container -//! for this AiffFile. -// -const AiffFile::markers_type & -AiffFile::markers( void ) const -{ - return markers_; -} - -// --------------------------------------------------------------------------- -// midiNoteNumber -// --------------------------------------------------------------------------- -//! Return the fractional MIDI note number assigned to this AiffFile. -//! If the sound has no definable pitch, note number 60.0 is used. -// -double -AiffFile::midiNoteNumber( void ) const -{ - return notenum_; -} - -// --------------------------------------------------------------------------- -// numChannels -// --------------------------------------------------------------------------- -//! Return the number of channels of audio samples represented by -//! this AiffFile, 1 for mono, 2 for stereo. -// -unsigned int -AiffFile::numChannels( void ) const -{ - return numchans_; -} - -// --------------------------------------------------------------------------- -// numFrames -// --------------------------------------------------------------------------- -//! Return the number of sample frames represented in this AiffFile. -//! A sample frame contains one sample per channel for a single sample -//! interval (e.g. mono and stereo samples files having a sample rate of -//! 44100 Hz both have 44100 sample frames per second of audio samples). -// - AiffFile::size_type - AiffFile::numFrames( void ) const - { - return samples_.size(); - } - -// --------------------------------------------------------------------------- -// sampleRate -// --------------------------------------------------------------------------- -//! Return the sampling freqency in Hz for the sample data in this -//! AiffFile. -// -double -AiffFile::sampleRate( void ) const -{ - return rate_; -} - -// --------------------------------------------------------------------------- -// samples -// --------------------------------------------------------------------------- -//! Return a reference (or const reference) to the vector containing -//! the floating-point sample data for this AiffFile. -// -AiffFile::samples_type & -AiffFile::samples( void ) -{ - return samples_; -} - -//! Return a const reference (or const reference) to the vector containing -//! the floating-point sample data for this AiffFile. -// -const AiffFile::samples_type & -AiffFile::samples( void ) const -{ - return samples_; -} - -// -- mutation -- - -// --------------------------------------------------------------------------- -// addPartial -// --------------------------------------------------------------------------- -//! Render the specified Partial using the (optionally) specified -//! Partial fade time (see Synthesizer.h for an examplanation -//! of fade time), and accumulate the resulting samples into -//! the sample vector for this AiffFile. Other synthesis parameters -//! are taken from the Synthesizer DefaultParameters. -//! -//! \sa Synthesizer::DefaultParameters -//! -//! \param p is the partial to render into this AiffFile -//! \param fadeTime is the Partial fade time for rendering -//! the Partials on the specified range. If unspecified, the -//! fade time is taken from the Synthesizer DefaultParameters. -// -void -AiffFile::addPartial( const Loris::Partial & p, double fadeTime ) -{ - Synthesizer synth = configureSynthesizer( fadeTime ); - synth.synthesize( p ); -} - -// --------------------------------------------------------------------------- -// setMidiNoteNumber -// --------------------------------------------------------------------------- -//! Set the fractional MIDI note number assigned to this AiffFile. -//! If the sound has no definable pitch, use note number 60.0 (the default). -//! -//! \param nn is a fractional MIDI note number, 60 is middle C. -// -void -AiffFile::setMidiNoteNumber( double nn ) -{ - if ( nn < 0 || nn > 128 ) - { - Throw( InvalidArgument, "MIDI note number outside of the valid range [1,128]" ); - } - notenum_ = nn; -} - -// -- helpers -- - -// --------------------------------------------------------------------------- -// configureSynthesizer -// --------------------------------------------------------------------------- -// Construct a Synthesizer for rendering Partials and set its fadeTime. -// Modify the default synthesizer parameters with this file's sample rate -// and, if specified (not equal to FadeTimeUnspecified), the fade time. -// -Synthesizer -AiffFile::configureSynthesizer( double fadeTime ) -{ - Synthesizer::Parameters params; - params.sampleRate = rate_; - - if ( FadeTimeUnspecified != fadeTime ) - { - params.fadeTime = fadeTime; - } - - return Synthesizer( params, samples_ ); -} - -// --------------------------------------------------------------------------- -// readAiffData -// --------------------------------------------------------------------------- -// Import data from an AIFF file on disk. -// -void -AiffFile::readAiffData( const std::string & filename ) -{ - ContainerCk containerChunk; - CommonCk commonChunk; - SoundDataCk soundDataChunk; - InstrumentCk instrumentChunk; - MarkerCk markerChunk; - - try - { - std::ifstream s( filename.c_str(), std::ifstream::binary ); - - // the Container chunk must be first, read it: - readChunkHeader( s, containerChunk.header ); - if ( !s ) - { - Throw( FileIOException, "File not found, or corrupted." ); - } - if ( containerChunk.header.id != ContainerId ) - { - Throw( FileIOException, "Found no Container chunk." ); - } - readContainer( s, containerChunk, containerChunk.header.size ); - - // read other chunks, we are only interested in - // the Common chunk, the Sound Data chunk, the Markers: - CkHeader h; - while ( readChunkHeader( s, h ) ) - { - switch (h.id) - { - case CommonId: - readCommonData( s, commonChunk, h.size ); - if ( commonChunk.channels != 1 ) - { - Throw( FileIOException, - "Loris only processes single-channel AIFF samples files." ); - } - if ( commonChunk.bitsPerSample != 8 && - commonChunk.bitsPerSample != 16 && - commonChunk.bitsPerSample != 24 && - commonChunk.bitsPerSample != 32 ) - { - Throw( FileIOException, "Unrecognized sample size." ); - } - break; - case SoundDataId: - readSampleData( s, soundDataChunk, h.size ); - break; - case InstrumentId: - readInstrumentData( s, instrumentChunk, h.size ); - break; - case MarkerId: - readMarkerData( s, markerChunk, h.size ); - break; - default: - s.ignore( h.size ); - } - } - - if ( ! commonChunk.header.id || ! soundDataChunk.header.id ) - { - Throw( FileIOException, - "Reached end of file before finding both a Common chunk and a Sound Data chunk." ); - } - } - catch ( Exception & ex ) - { - ex.append( " Failed to read AIFF file." ); - throw; - } - - - // all the chunks have been read, use them to initialize - // the AiffFile members: - rate_ = commonChunk.srate; - - if ( instrumentChunk.header.id ) - { - notenum_ = instrumentChunk.baseNote; - notenum_ -= 0.01 * instrumentChunk.detune; - } - - if ( markerChunk.header.id ) - { - for ( int j = 0; j < markerChunk.numMarkers; ++j ) - { - MarkerCk::Marker & m = markerChunk.markers[j]; - markers_.push_back( Marker( m.position / rate_, m.markerName ) ); - } - } - - convertBytesToSamples( soundDataChunk.sampleBytes, samples_, commonChunk.bitsPerSample ); - if ( samples_.size() != commonChunk.sampleFrames ) - { - notifier << "Found " << samples_.size() << " frames of " - << commonChunk.bitsPerSample << "-bit sample data." << endl; - notifier << "Header says there should be " << commonChunk.sampleFrames - << "." << endl; - } -} - - -} // end of namespace Loris diff --git a/loris_library/Source/src/AiffFile.h b/loris_library/Source/src/AiffFile.h deleted file mode 100644 index 55c2bc7..0000000 --- a/loris_library/Source/src/AiffFile.h +++ /dev/null @@ -1,388 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * AiffFile.h - * - * Definition of AiffFile class for sample import and export in Loris. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "Marker.h" -#include "Synthesizer.h" - -#if defined(NO_TEMPLATE_MEMBERS) -#include "PartialList.h" -#endif - -#include -#include -#include - -// begin namespace -namespace Loris { - -class Partial; - -// --------------------------------------------------------------------------- -// class AiffFile -// -//! Class AiffFile represents sample data in a AIFF-format samples -//! file, and manages file I/O and sample conversion. Since the sound -//! analysis and synthesis algorithms in Loris and the reassigned -//! bandwidth-enhanced representation are monaural, AiffFile imports -//! only monaural (single channel) AIFF-format samples files, though -//! it can create and export a new two-channel file from a pair of -//! sample vectors. -// -class AiffFile -{ -// -- public interface -- -public: - -// -- types -- - - //! The type of the sample storage in an AiffFile. - typedef std::vector< double > samples_type; - - //! The type of all size parameters for AiffFile. - typedef samples_type::size_type size_type; - - //! The type of AIFF marker storage in an AiffFile. - typedef std::vector< Marker > markers_type; - -// -- construction -- - - //! Initialize an instance of AiffFile by importing sample data from - //! the file having the specified filename or path. - //! - //! \param filename is the name or path of an AIFF samples file - explicit AiffFile( const std::string & filename ); - - //! Initialize an instance of AiffFile with samples rendered - //! from a sequnence of Partials. The Partials in the - //! specified half-open (STL-style) range are rendered at - //! the specified sample rate, using the (optionally) - //! specified Partial fade time (see Synthesizer.h - //! for an examplanation of fade time). Other synthesis - //! parameters are taken from the Synthesizer DefaultParameters. - //! - //! \sa Synthesizer::DefaultParameters - //! - //! \param begin_partials is the beginning of a sequence of Partials - //! \param end_partials is (one-past) the end of a sequence of - //! Partials - //! \param samplerate is the rate (Hz) at which Partials are rendered - //! \param fadeTime is the Partial fade time (seconds) for rendering - //! the Partials on the specified range. If unspecified, the - //! fade time is taken from the Synthesizer DefaultParameters. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. -#if !defined(NO_TEMPLATE_MEMBERS) - template - AiffFile( Iter begin_partials, Iter end_partials, - double samplerate, double fadeTime = FadeTimeUnspecified ); -#else - AiffFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double samplerate, double fadeTime = FadeTimeUnspecified ); -#endif - - //! Initialize an instance of AiffFile having the specified sample - //! rate, preallocating numFrames samples, initialized to zero. - //! - //! \param samplerate is the rate at which Partials are rendered - //! \param numFrames is the initial number of (zero) samples. If - //! unspecified, no samples are preallocated. - //! \param numChannels is the number of channels of audio data - //! to preallocate (default 1 channel) - AiffFile( double samplerate, size_type numFrames = 0, - unsigned int numChannels = 1 ); - - //! Initialize an instance of AiffFile from a buffer of sample - //! data, with the specified sample rate. - //! - //! \param buffer is a pointer to a buffer of floating point samples. - //! \param bufferlength is the number of samples in the buffer. - //! \param samplerate is the sample rate of the samples in the buffer. - AiffFile( const double * buffer, size_type bufferlength, double samplerate ); - - //! Initialize an instance of AiffFile from two buffers of sample - //! data, with the specified sample rate. Both buffers must store - //! the same number (bufferLength) of samples. - //! - //! \param buffer_left is a pointer to a buffer of floating point samples - //! representing the left channel samples. - //! \param buffer_right is a pointer to a buffer of floating point samples - //! representing the right channel samples. - //! \param bufferlength is the number of samples in the buffer. - //! \param samplerate is the sample rate of the samples in the buffer. - // - AiffFile( const double * buffer_left, const double * buffer_right, - size_type bufferlength, double samplerate ); - - //! Initialize an instance of AiffFile from a vector of sample - //! data, with the specified sample rate. - //! - //! \param vec is a vector of floating point samples. - //! \param samplerate is the sample rate of the samples in the vector. - AiffFile( const std::vector< double > & vec, double samplerate ); - - //! Initialize an instance of AiffFile from two vectors of sample - //! data, with the specified sample rate. If the two vectors have different - //! lengths, the shorter one is padded with zeros. - //! - //! \param vec_left is a vector of floating point samples representing the - //! left channel samples. - //! \param vec_right is a vector of floating point samples representing the - //! right channel samples. - //! \param samplerate is the sample rate of the samples in the vectors. - // - AiffFile( const std::vector< double > & vec_left, - const std::vector< double > & vec_right, - double samplerate ); - - //! Initialize this and AiffFile that is an exact copy, having - //! all the same sample data, as another AiffFile. - //! - //! \param other is the AiffFile to copy - AiffFile( const AiffFile & other ); - - //! Assignment operator: change this AiffFile to be an exact copy - //! of the specified AiffFile, rhs, that is, having the same sample - //! data. - //! - //! \param rhs is the AiffFile to replicate - AiffFile & operator= ( const AiffFile & rhs ); - -// -- access -- - - //! Return a reference to the Marker (see Marker.h) container - //! for this AiffFile. - markers_type & markers( void ); - - //! Return a const reference to the Marker (see Marker.h) container - //! for this AiffFile. - const markers_type & markers( void ) const; - - //! Return the fractional MIDI note number assigned to this AiffFile. - //! If the sound has no definable pitch, note number 60.0 is used. - double midiNoteNumber( void ) const; - - //! Return the number of channels of audio samples represented by - //! this AiffFile, 1 for mono, 2 for stereo. - unsigned int numChannels( void ) const; - - //! Return the number of sample frames represented in this AiffFile. - //! A sample frame contains one sample per channel for a single sample - //! interval (e.g. mono and stereo samples files having a sample rate of - //! 44100 Hz both have 44100 sample frames per second of audio samples). - size_type numFrames( void ) const; - - //! Bad old legacy name for numFrames. - //! \deprecated Use numFrames instead. - size_type sampleFrames( void ) const { return numFrames(); } - - //! Return the sampling freqency in Hz for the sample data in this - //! AiffFile. - double sampleRate( void ) const; - - //! Return a reference (or const reference) to the vector containing - //! the floating-point sample data for this AiffFile. - samples_type & samples( void ); - - //! Return a const reference (or const reference) to the vector containing - //! the floating-point sample data for this AiffFile. - const samples_type & samples( void ) const; - -// -- mutation -- - - //! Render the specified Partial using the (optionally) specified - //! Partial fade time (see Synthesizer.h for an examplanation - //! of fade time), and accumulate the resulting samples into - //! the sample vector for this AiffFile. Other synthesis parameters - //! are taken from the Synthesizer DefaultParameters. - //! - //! \sa Synthesizer::DefaultParameters - //! - //! \param p is the partial to render into this AiffFile - //! \param fadeTime is the Partial fade time for rendering - //! the Partials on the specified range. If unspecified, the - //! fade time is taken from the Synthesizer DefaultParameters. - void addPartial( const Loris::Partial & p, double fadeTime = FadeTimeUnspecified ); - - //! Accumulate samples rendered from a sequence of Partials. - //! The Partials in the specified half-open (STL-style) range are - //! rendered at this AiffFile's sample rate, using the (optionally) - //! specified Partial fade time (see Synthesizer.h for an examplanation - //! of fade time). Other synthesis parameters are taken from the - //! Synthesizer DefaultParameters. - //! - //! \sa Synthesizer::DefaultParameters - //! - //! \param begin_partials is the beginning of a sequence of Partials - //! \param end_partials is (one-past) the end of a sequence of - //! Partials - //! \param fadeTime is the Partial fade time for rendering - //! the Partials on the specified range. If unspecified, the - //! fade time is taken from the Synthesizer DefaultParameters. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. -#if !defined(NO_TEMPLATE_MEMBERS) - template - void addPartials( Iter begin_partials, Iter end_partials, - double fadeTime = FadeTimeUnspecified ); -#else - void addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double fadeTime = FadeTimeUnspecified ); -#endif - - //! Set the fractional MIDI note number assigned to this AiffFile. - //! If the sound has no definable pitch, use note number 60.0 (the default). - //! - //! \param nn is a fractional MIDI note number, 60 is middle C. - void setMidiNoteNumber( double nn ); - -// -- export -- - - //! Export the sample data represented by this AiffFile to - //! the file having the specified filename or path. Export - //! signed integer samples of the specified size, in bits - //! (8, 16, 24, or 32). - //! - //! \param filename is the name or path of the AIFF samples file - //! to be created or overwritten. - //! \param bps is the number of bits per sample to store in the - //! samples file (8, 16, 24, or 32).If unspeicified, 16 bits - void write( const std::string & filename, unsigned int bps = 16 ); - -private: -// -- implementation -- - double notenum_, rate_; // MIDI note number and sample rate - unsigned int numchans_; - markers_type markers_; // AIFF Markers - samples_type samples_; // floating point samples [-1.0, 1.0] - - -// -- helpers -- - - // Construct a Synthesizer for rendering Partials and set its fadeTime. - // Modify the default synthesizer parameters with this file's sample rate - // and, if specified (not equal to FadeTimeUnspecified), the fade time. - Synthesizer configureSynthesizer( double fadeTime ); - - // Import data from an AIFF file on disk. - void readAiffData( const std::string & filename ); - - enum { FadeTimeUnspecified = -9999999 }; - // This is not pretty, but it is better (perhaps) than defining two - // of every member having an optional fade time parameter. - -}; // end of class AiffFile - -// -- template members -- - -// --------------------------------------------------------------------------- -// constructor from Partial range -// --------------------------------------------------------------------------- -//! Initialize an instance of AiffFile with samples rendered -//! from a sequnence of Partials. The Partials in the -//! specified half-open (STL-style) range are rendered at -//! the specified sample rate, using the (optionally) -//! specified Partial fade time (see Synthesizer.h -//! for an examplanation of fade time). Other synthesis -//! parameters are taken from the Synthesizer DefaultParameters. -//! -//! \sa Synthesizer::DefaultParameters -//! -//! \param begin_partials is the beginning of a sequence of Partials -//! \param end_partials is (one-past) the end of a sequence of -//! Partials -//! \param samplerate is the rate (Hz) at which Partials are rendered -//! \param fadeTime is the Partial fade time (seconds) for rendering -//! the Partials on the specified range. If unspecified, the -//! fade time is taken from the Synthesizer DefaultParameters. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. -// -#if !defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > - AiffFile::AiffFile( Iter begin_partials, Iter end_partials, - double samplerate, double fadeTime ) : -#else - AiffFile::AiffFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double samplerate, double fadeTime ) : -#endif -// initializers: - notenum_( 60 ), - rate_( samplerate ), - numchans_( 1 ) -{ - addPartials( begin_partials, end_partials, fadeTime ); -} - -// --------------------------------------------------------------------------- -// addPartials -// --------------------------------------------------------------------------- -//! Accumulate samples rendered from a sequence of Partials. -//! The Partials in the specified half-open (STL-style) range are -//! rendered at this AiffFile's sample rate, using the (optionally) -//! specified Partial fade time (see Synthesizer.h for an examplanation -//! of fade time). Other synthesis parameters are taken from the -//! Synthesizer DefaultParameters. -//! -//! \sa Synthesizer::DefaultParameters -//! -//! \param begin_partials is the beginning of a sequence of Partials -//! \param end_partials is (one-past) the end of a sequence of -//! Partials -//! \param fadeTime is the Partial fade time for rendering -//! the Partials on the specified range. If unspecified, the -//! fade time is taken from the Synthesizer DefaultParameters. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. -// -#if !defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void - AiffFile::addPartials( Iter begin_partials, Iter end_partials, double fadeTime ) -#else -void - AiffFile::addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double fadeTime ) -#endif -{ - Synthesizer synth = configureSynthesizer( fadeTime ); - synth.synthesize( begin_partials, end_partials ); -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Analyzer.cpp b/loris_library/Source/src/Analyzer.cpp deleted file mode 100644 index 89b2ab9..0000000 --- a/loris_library/Source/src/Analyzer.cpp +++ /dev/null @@ -1,1427 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Analyzer.C - * - * Implementation of class Loris::Analyzer. - * - * Kelly Fitz, 5 Dec 99 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Analyzer.h" - -#include "AssociateBandwidth.h" -#include "Breakpoint.h" -#include "BreakpointEnvelope.h" -#include "Envelope.h" -#include "F0Estimate.h" -#include "LorisExceptions.h" -#include "KaiserWindow.h" -#include "Notifier.h" -#include "Partial.h" -#include "PartialPtrs.h" -#include "ReassignedSpectrum.h" -#include "SpectralPeakSelector.h" -#include "PartialBuilder.h" - -#include "phasefix.h" // for frequency/phase fixing at end of analysis - - - -#include -#include -#include // for std::plus -#include -#include // for std::inner_product -#include -#include - -using namespace std; - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// helpers, used below -// --------------------------------------------------------------------------- -static double accumPeakSquaredAmps( double init, - const SpectralPeak & pk ) -{ - return init + (pk.amplitude() * pk.amplitude()); -} - -template < class Pair > -static double compare2nd( const Pair & p1, const Pair & p2 ) -{ - return p1.second < p2.second; -} - -// --------------------------------------------------------------------------- -// LinearEnvelopeBuilder -// --------------------------------------------------------------------------- -// Base class for envelope builders that add a point (possibly) at each -// analysis frame. -// -// TODO: make a dictionary of these things and allow clients to add their -// own envelope builders and builder functions, and retrieve them after -// analysis. -class LinearEnvelopeBuilder -{ -public: - virtual ~LinearEnvelopeBuilder( void ) {} - virtual LinearEnvelopeBuilder * clone( void ) const = 0; - virtual void build( const Peaks & peaks, double frameTime ) = 0; - - const LinearEnvelope & envelope( void ) const { return mEnvelope; } - - // reset (clear) envelope, override if necesssary: - virtual void reset( void ) { mEnvelope.clear(); } - -protected: - - LinearEnvelope mEnvelope; // build this -}; - -// --------------------------------------------------------------------------- -// FundamentalBuilder - for constructing an F0 envelope during analysis -// --------------------------------------------------------------------------- -class FundamentalBuilder : public LinearEnvelopeBuilder -{ - std::auto_ptr< Envelope > mFminEnv; - std::auto_ptr< Envelope > mFmaxEnv; - - double mAmpThresh, mFreqThresh; - - std::vector< double > amplitudes, frequencies; - - const double mMinConfidence; // 0.9, this could be made a parameter, - // or raised to make estimates smoother - -public: - FundamentalBuilder( double fmin, double fmax, double threshDb = -60, double threshHz = 8000 ) : - mFminEnv( new LinearEnvelope( fmin ) ), - mFmaxEnv( new LinearEnvelope( fmax ) ), - mAmpThresh( std::pow( 10., 0.05*(threshDb) ) ), - mFreqThresh( threshHz ), - mMinConfidence( 0.9 ) - {} - - FundamentalBuilder( const Envelope & fmin, const Envelope & fmax, - double threshDb = -60, double threshHz = 8000 ) : - mFminEnv( fmin.clone() ), - mFmaxEnv( fmax.clone() ), - mAmpThresh( std::pow( 10., 0.05*(threshDb) ) ), - mFreqThresh( threshHz ), - mMinConfidence( 0.9 ) - {} - - FundamentalBuilder( const FundamentalBuilder & rhs ) : - mFminEnv( rhs.mFminEnv->clone() ), - mFmaxEnv( rhs.mFmaxEnv->clone() ), - mAmpThresh( rhs.mAmpThresh ), - mFreqThresh( rhs.mFreqThresh ), - mMinConfidence( rhs.mMinConfidence ) - {} - - - FundamentalBuilder * clone( void ) const { return new FundamentalBuilder(*this); } - - void build( const Peaks & peaks, double frameTime ); -}; - -// --------------------------------------------------------------------------- -// FundamentalBuilder::build -// --------------------------------------------------------------------------- -// -void FundamentalBuilder::build( const Peaks & peaks, double frameTime ) -{ - amplitudes.clear(); - frequencies.clear(); - for ( Peaks::const_iterator spkpos = peaks.begin(); spkpos != peaks.end(); ++spkpos ) - { - if ( spkpos->amplitude() > mAmpThresh && - spkpos->frequency() < mFreqThresh ) - { - amplitudes.push_back( spkpos->amplitude() ); - frequencies.push_back( spkpos->frequency() ); - } - } - if ( ! amplitudes.empty() ) - { - const double fmin = mFminEnv->valueAt( frameTime ); - const double fmax = mFmaxEnv->valueAt( frameTime ); - - // estimate f0 - F0Estimate est( amplitudes, frequencies, fmin, fmax, 0.1 ); - - if ( est.confidence() >= mMinConfidence && - est.frequency() > fmin && est.frequency() < fmax ) - { - // notifier << "f0 is " << est.frequency << endl; - // add breakpoint to fundamental envelope - mEnvelope.insert( frameTime, est.frequency() ); - } - } - -} - -// --------------------------------------------------------------------------- -// AmpEnvBuilder - for constructing an amplitude envelope during analysis -// --------------------------------------------------------------------------- -class AmpEnvBuilder : public LinearEnvelopeBuilder -{ -public: - AmpEnvBuilder( void ) {} - - AmpEnvBuilder * clone( void ) const { return new AmpEnvBuilder(*this); } - - void build( const Peaks & peaks, double frameTime ); - -}; - -// --------------------------------------------------------------------------- -// AmpEnvBuilder::build -// --------------------------------------------------------------------------- -// -void AmpEnvBuilder::build( const Peaks & peaks, double frameTime ) -{ - double x = std::accumulate( peaks.begin(), peaks.end(), 0.0, accumPeakSquaredAmps ); - mEnvelope.insert( frameTime, std::sqrt( x ) ); -} - - -// --------------------------------------------------------------------------- -// Analyzer constructor - frequency resolution only -// --------------------------------------------------------------------------- -//! Construct a new Analyzer configured with the given -//! frequency resolution (minimum instantaneous frequency -//! difference between Partials). All other Analyzer parameters -//! are computed from the specified frequency resolution. -//! -//! \param resolutionHz is the frequency resolution in Hz. -// -Analyzer::Analyzer( double resolutionHz ) -{ - configure( resolutionHz, 2.0 * resolutionHz ); -} - -// --------------------------------------------------------------------------- -// Analyzer constructor -// --------------------------------------------------------------------------- -//! Construct a new Analyzer configured with the given -//! frequency resolution (minimum instantaneous frequency -//! difference between Partials) and analysis window width -//! (main lobe, zero-to-zero). All other Analyzer parameters -//! are computed from the specified resolution and window width. -//! -//! \param resolutionHz is the frequency resolution in Hz. -//! \param windowWidthHz is the main lobe width of the Kaiser -//! analysis window in Hz. -// -Analyzer::Analyzer( double resolutionHz, double windowWidthHz ) -{ - configure( resolutionHz, windowWidthHz ); -} - -// --------------------------------------------------------------------------- -// Analyzer constructor -// --------------------------------------------------------------------------- -//! Construct a new Analyzer configured with the given time-varying -//! frequency resolution (minimum instantaneous frequency -//! difference between Partials) and analysis window width -//! (main lobe, zero-to-zero). All other Analyzer parameters -//! are computed from the specified resolution and window width. -//! -//! \param resolutionHz is the frequency resolution in Hz. -//! \param windowWidthHz is the main lobe width of the Kaiser -//! analysis window in Hz. -// -Analyzer::Analyzer( const Envelope & resolutionEnv, double windowWidthHz ) -{ - configure( resolutionEnv, windowWidthHz ); -} - -// --------------------------------------------------------------------------- -// Analyzer copy constructor -// --------------------------------------------------------------------------- -//! Construct a new Analyzer having identical -//! parameter configuration to another Analyzer. -//! The list of collected Partials is not copied. -//! -//! \param other is the Analyzer to copy. -// -Analyzer::Analyzer( const Analyzer & other ) : - m_freqResolutionEnv( other.m_freqResolutionEnv->clone() ), - m_ampFloor( other.m_ampFloor ), - m_windowWidth( other.m_windowWidth ), - m_freqFloor( other.m_freqFloor ), - m_freqDrift( other.m_freqDrift ), - m_hopTime( other.m_hopTime ), - m_cropTime( other.m_cropTime ), - m_bwAssocParam( other.m_bwAssocParam ), - m_sidelobeLevel( other.m_sidelobeLevel ), - m_phaseCorrect( other.m_phaseCorrect ), - m_partials( other.m_partials ) -{ - m_f0Builder.reset( other.m_f0Builder->clone() ); - m_ampEnvBuilder.reset( other.m_ampEnvBuilder->clone() ); -} - -// --------------------------------------------------------------------------- -// Analyzer assignment -// --------------------------------------------------------------------------- -//! Construct a new Analyzer having identical -//! parameter configuration to another Analyzer. -//! The list of collected Partials is not copied. -//! -//! \param rhs is the Analyzer to copy. -// -Analyzer & -Analyzer::operator=( const Analyzer & rhs ) -{ - if ( this != & rhs ) - { - m_freqResolutionEnv.reset( rhs.m_freqResolutionEnv->clone() ); - m_ampFloor = rhs.m_ampFloor; - m_windowWidth = rhs.m_windowWidth; - m_freqFloor = rhs.m_freqFloor; - m_freqDrift = rhs.m_freqDrift; - m_hopTime = rhs.m_hopTime; - m_cropTime = rhs.m_cropTime; - m_bwAssocParam = rhs.m_bwAssocParam; - m_sidelobeLevel = rhs.m_sidelobeLevel; - m_phaseCorrect = rhs.m_phaseCorrect; - m_partials = rhs.m_partials; - - m_f0Builder.reset( rhs.m_f0Builder->clone() ); - m_ampEnvBuilder.reset( rhs.m_ampEnvBuilder->clone() ); - - } - return *this; -} - -// --------------------------------------------------------------------------- -// Analyzer destructor -// --------------------------------------------------------------------------- -//! Destroy this Analyzer. -// -Analyzer::~Analyzer( void ) -{ -} - -// -- configuration -- - -// --------------------------------------------------------------------------- -// configure -// --------------------------------------------------------------------------- -//! Configure this Analyzer with the given frequency resolution -//! (minimum instantaneous frequency difference between Partials, -//! in Hz). All other Analyzer parameters are (re-)computed from the -//! frequency resolution, including the window width, which is -//! twice the resolution. -//! -//! \param resolutionHz is the frequency resolution in Hz. -// -void -Analyzer::configure( double resolutionHz ) -{ - configure( resolutionHz, 2.0 * resolutionHz ); -} - -// --------------------------------------------------------------------------- -// configure -// --------------------------------------------------------------------------- -//! Configure this Analyzer with the given frequency resolution -//! (minimum instantaneous frequency difference between Partials) -//! and analysis window width (main lobe, zero-to-zero, in Hz). -//! All other Analyzer parameters are (re-)computed from the -//! frequency resolution and window width. -//! -//! \param resolutionHz is the frequency resolution in Hz. -//! \param windowWidthHz is the main lobe width of the Kaiser -//! analysis window in Hz. -//! -//! There are three categories of analysis parameters: -//! - the resolution, and params that are usually related to (or -//! identical to) the resolution (frequency floor and drift) -//! - the window width and params that are usually related to (or -//! identical to) the window width (hop and crop times) -//! - independent parameters (bw region width and amp floor) -// -void -Analyzer::configure( double resolutionHz, double windowWidthHz ) -{ - // use specified resolution: - setFreqResolution( resolutionHz ); - - // floor defaults to -90 dB: - setAmpFloor( -90. ); - - // window width should generally be approximately - // equal to, and never more than twice the - // frequency resolution: - setWindowWidth( windowWidthHz ); - - // the Kaiser window sidelobe level can be the same - // as the amplitude floor (except in positive dB): - setSidelobeLevel( - m_ampFloor ); - - // for the minimum frequency, below which no data is kept, - // use the frequency resolution by default (this makes - // Lip happy, and is always safe?) and allow the client - // to change it to anything at all. - setFreqFloor( resolutionHz ); - - // frequency drift in Hz is the maximum difference - // in frequency between consecutive Breakpoints in - // a Partial, by default, make it equal to one half - // the frequency resolution: - setFreqDrift( .5 * resolutionHz ); - - // hop time (in seconds) is the inverse of the - // window width....really. Smith and Serra (1990) cite - // Allen (1977) saying: a good choice of hop is the window - // length divided by the main lobe width in frequency samples, - // which turns out to be just the inverse of the width. - setHopTime( 1. / m_windowWidth ); - - // crop time (in seconds) is the maximum allowable time - // correction, beyond which a reassigned spectral component - // is considered unreliable, and not considered eligible for - // Breakpoint formation in extractPeaks(). By default, use - // the hop time (should it be half that?): - setCropTime( m_hopTime ); - - // bandwidth association region width - // defaults to 2 kHz, corresponding to - // 1 kHz region center spacing: - storeResidueBandwidth(); - - // configure the envelope builders using default - // parameters: - buildFundamentalEnv( 0.99 * resolutionHz, - 1.5 * resolutionHz ); - m_ampEnvBuilder.reset( new AmpEnvBuilder ); - - // enable phase-correct Partial construction: - m_phaseCorrect = true; -} - -// --------------------------------------------------------------------------- -// configure -// --------------------------------------------------------------------------- -//! Configure this Analyzer with the given time-varying frequency resolution -//! (minimum instantaneous frequency difference between Partials) -//! and analysis window width (main lobe, zero-to-zero, in Hz). -//! All other Analyzer parameters are (re-)computed from the -//! frequency resolution and window width. -//! -//! \param resolutionEnv is the time-varying frequency resolution -//! in Hz. -//! \param windowWidthHz is the main lobe width of the Kaiser -//! analysis window in Hz. -//! -//! There are three categories of analysis parameters: -//! - the resolution, and params that are usually related to (or -//! identical to) the resolution (frequency floor and drift) -//! - the window width and params that are usually related to (or -//! identical to) the window width (hop and crop times) -//! - independent parameters (bw region width and amp floor) -// -void -Analyzer::configure( const Envelope & resolutionEnv, double windowWidthHz ) -{ - // use specified resolution: - setFreqResolution( resolutionEnv ); - - // floor defaults to -90 dB: - setAmpFloor( -90. ); - - // window width should generally be approximately - // equal to, and never more than twice the - // frequency resolution: - setWindowWidth( windowWidthHz ); - - // the Kaiser window sidelobe level can be the same - // as the amplitude floor (except in positive dB): - setSidelobeLevel( - m_ampFloor ); - - // for the minimum frequency, below which no data is kept, - // use the frequency resolution by default (this makes - // Lip happy, and is always safe?) and allow the client - // to change it to anything at all. - setFreqFloor( windowWidthHz * 0.5 ); // !!!!! - - // frequency drift in Hz is the maximum difference - // in frequency between consecutive Breakpoints in - // a Partial, by default, make it equal to one half - // the frequency resolution: - setFreqDrift( windowWidthHz * 0.25 ); // !!!!! - - // hop time (in seconds) is the inverse of the - // window width....really. Smith and Serra (1990) cite - // Allen (1977) saying: a good choice of hop is the window - // length divided by the main lobe width in frequency samples, - // which turns out to be just the inverse of the width. - setHopTime( 1. / m_windowWidth ); - - // crop time (in seconds) is the maximum allowable time - // correction, beyond which a reassigned spectral component - // is considered unreliable, and not considered eligible for - // Breakpoint formation in extractPeaks(). By default, use - // the hop time (should it be half that?): - setCropTime( m_hopTime ); - - // bandwidth association region width - // defaults to 2 kHz, corresponding to - // 1 kHz region center spacing: - storeResidueBandwidth(); - - // configure the envelope builders using default - // parameters: - /* - buildFundamentalEnv( *m_freqResolutionEnv * 0.99, - *m_freqResolutionEnv * 1.5 ); - - */ // !!!!!!! - m_f0Builder.reset( - new FundamentalBuilder( *m_freqResolutionEnv * 0.99, - *m_freqResolutionEnv * 1.5, - -60., 8000. ) ); - - m_ampEnvBuilder.reset( new AmpEnvBuilder ); - - // enable phase-correct Partial construction: - m_phaseCorrect = true; -} - -// -- analysis -- -// --------------------------------------------------------------------------- -// analyze -// --------------------------------------------------------------------------- -//! Analyze a vector of (mono) samples at the given sample rate -//! (in Hz) and store the extracted Partials in the Analyzer's -//! PartialList (std::list of Partials). -//! -//! \param vec is a vector of floating point samples -//! \param srate is the sample rate of the samples in the vector -// -void -Analyzer::analyze( const std::vector & vec, double srate ) -{ - BreakpointEnvelope reference( 1.0 ); - analyze( &(vec[0]), &(vec[0]) + vec.size(), srate, reference ); -} - -// --------------------------------------------------------------------------- -// analyze -// --------------------------------------------------------------------------- -//! Analyze a range of (mono) samples at the given sample rate -//! (in Hz) and store the extracted Partials in the Analyzer's -//! PartialList (std::list of Partials). -//! -//! \param bufBegin is a pointer to a buffer of floating point samples -//! \param bufEnd is (one-past) the end of a buffer of floating point -//! samples -//! \param srate is the sample rate of the samples in the buffer -// -void -Analyzer::analyze( const double * bufBegin, const double * bufEnd, double srate ) -{ - BreakpointEnvelope reference( 1.0 ); - analyze( bufBegin, bufEnd, srate, reference ); -} - -// --------------------------------------------------------------------------- -// analyze -// --------------------------------------------------------------------------- -//! Analyze a vector of (mono) samples at the given sample rate -//! (in Hz) and store the extracted Partials in the Analyzer's -//! PartialList (std::list of Partials). Use the specified envelope -//! as a frequency reference for Partial tracking. -//! -//! \param vec is a vector of floating point samples -//! \param srate is the sample rate of the samples in the vector -//! \param reference is an Envelope having the approximate -//! frequency contour expected of the resulting Partials. -// -void -Analyzer::analyze( const std::vector & vec, double srate, - const Envelope & reference ) -{ - analyze( &(vec[0]), &(vec[0]) + vec.size(), srate, reference ); -} - - -// --------------------------------------------------------------------------- -// analyze -// --------------------------------------------------------------------------- -//! Analyze a range of (mono) samples at the given sample rate -//! (in Hz) and store the extracted Partials in the Analyzer's -//! PartialList (std::list of Partials). Use the specified envelope -//! as a frequency reference for Partial tracking. -//! -//! \param bufBegin is a pointer to a buffer of floating point samples -//! \param bufEnd is (one-past) the end of a buffer of floating point -//! samples -//! \param srate is the sample rate of the samples in the buffer -//! \param reference is an Envelope having the approximate -//! frequency contour expected of the resulting Partials. -// -void -Analyzer::analyze( const double * bufBegin, const double * bufEnd, double srate, - const Envelope & reference ) -{ - // configure the reassigned spectral analyzer, - // always use odd-length windows: - - // Kaiser window - double winshape = KaiserWindow::computeShape( sidelobeLevel() ); - long winlen = KaiserWindow::computeLength( windowWidth() / srate, winshape ); - if (! (winlen % 2)) - { - ++winlen; - } - debugger << "Using Kaiser window of length " << winlen << endl; - - std::vector< double > window( winlen ); - KaiserWindow::buildWindow( window, winshape ); - - std::vector< double > windowDeriv( winlen ); - KaiserWindow::buildTimeDerivativeWindow( windowDeriv, winshape ); - - ReassignedSpectrum spectrum( window, windowDeriv ); - - // configure the peak selection and partial formation policies: - SpectralPeakSelector selector( srate, m_cropTime ); - PartialBuilder builder( m_freqDrift, reference ); - - // configure bw association policy, unless - // bandwidth association is disabled: - std::auto_ptr< AssociateBandwidth > bwAssociator; - if( m_bwAssocParam > 0 ) - { - debugger << "Using bandwidth association regions of width " - << bwRegionWidth() << " Hz" << endl; - bwAssociator.reset( new AssociateBandwidth( bwRegionWidth(), srate ) ); - } - else - { - debugger << "Bandwidth association disabled" << endl; - } - - // reset envelope builders: - m_ampEnvBuilder->reset(); - m_f0Builder->reset(); - - m_partials.clear(); - - try - { - const double * winMiddle = bufBegin; - - // loop over short-time analysis frames: - while ( winMiddle < bufEnd ) - { - - - // compute the time of this analysis frame: - const double currentFrameTime = long(winMiddle - bufBegin) / srate; - - const double totalLength = (double)(bufEnd - bufBegin) / srate; - - if (threadController != nullptr && !threadController->setProgress(currentFrameTime / totalLength)) - throw Exception("cancelled"); - - // compute reassigned spectrum: - // sampsBegin is the position of the first sample to be transformed, - // sampsEnd is the position after the last sample to be transformed. - // (these computations work for odd length windows only) - const double * sampsBegin = std::max( winMiddle - (winlen / 2), bufBegin ); - const double * sampsEnd = std::min( winMiddle + (winlen / 2) + 1, bufEnd ); - spectrum.transform( sampsBegin, winMiddle, sampsEnd ); - - - // extract peaks from the spectrum, and thin - Peaks peaks = selector.selectPeaks( spectrum, m_freqFloor ); - Peaks::iterator rejected = thinPeaks( peaks, currentFrameTime ); - - // fix the stored bandwidth values - // KLUDGE: need to do this before the bandwidth - // associator tries to do its job, because the mixed - // derivative is temporarily stored in the Breakpoint - // bandwidth!!! FIX!!!! - fixBandwidth( peaks ); - - if ( m_bwAssocParam > 0 ) - { - bwAssociator->associateBandwidth( peaks.begin(), rejected, peaks.end() ); - } - - // remove rejected Breakpoints (needed above to - // compute bandwidth envelopes): - peaks.erase( rejected, peaks.end() ); - - // estimate the amplitude in this frame: - m_ampEnvBuilder->build( peaks, currentFrameTime ); - - // collect amplitudes and frequencies and try to - // estimate the fundamental - m_f0Builder->build( peaks, currentFrameTime ); - - // form Partials from the extracted Breakpoints: - builder.buildPartials( peaks, currentFrameTime ); - - // slide the analysis window: - winMiddle += long( m_hopTime * srate ); // hop in samples, truncated - - } // end of loop over short-time frames - - // unwarp the Partial frequency envelopes: - builder.finishBuilding( m_partials ); - - // fix the frequencies and phases to be consistent. - if ( m_phaseCorrect ) - { - fixFrequency( m_partials.begin(), m_partials.end() ); - } - - - // for debugging: - /* - if ( ! m_ampEnv.empty() ) - { - LinearEnvelope::iterator peakpos = - std::max_element( m_ampEnv.begin(), m_ampEnv.end(), - compare2nd ); - notifier << "Analyzer found amp peak at time : " << peakpos->first - << " value: " << peakpos->second << endl; - } - */ - } - catch ( Exception & ex ) - { - ex.append( "analysis failed." ); - throw; - } -} - -// -- parameter access -- - -// --------------------------------------------------------------------------- -// ampFloor -// --------------------------------------------------------------------------- -//! Return the amplitude floor (lowest detected spectral amplitude), -//! in (negative) dB, for this Analyzer. -// -double -Analyzer::ampFloor( void ) const -{ - return m_ampFloor; -} - -// --------------------------------------------------------------------------- -// cropTime -// --------------------------------------------------------------------------- -//! Return the crop time (maximum temporal displacement of a time- -//! frequency data point from the time-domain center of the analysis -//! window, beyond which data points are considered "unreliable") -//! for this Analyzer. -// -double -Analyzer::cropTime( void ) const -{ - // debugger << "Analyzer::cropTime() is a deprecated member, and will be removed in a future Loris release." << endl; - return m_cropTime; -} - -// --------------------------------------------------------------------------- -// freqDrift -// --------------------------------------------------------------------------- -//! Return the maximum allowable frequency difference -//! consecutive Breakpoints in a Partial envelope for this Analyzer. -// -double -Analyzer::freqDrift( void ) const -{ - return m_freqDrift; -} - -// --------------------------------------------------------------------------- -// freqFloor -// --------------------------------------------------------------------------- -//! Return the frequency floor (minimum instantaneous Partial -//! frequency), in Hz, for this Analyzer. -// -double -Analyzer::freqFloor( void ) const -{ - return m_freqFloor; -} - -// --------------------------------------------------------------------------- -// freqResolution -// --------------------------------------------------------------------------- -//! Return the frequency resolution (minimum instantaneous frequency -//! difference between Partials) for this Analyzer at the specified -//! time in seconds. If no time is specified, then the initial resolution -//! (at 0 seconds) is returned. -//! -//! \param time is the time in seconds at which to evaluate the -//! frequency resolution -// -double -Analyzer::freqResolution( double time /* = 0.0 */ ) const -{ - return m_freqResolutionEnv->valueAt( time ); -} - -// --------------------------------------------------------------------------- -// hopTime -// --------------------------------------------------------------------------- -//! Return the hop time (which corresponds approximately to the -//! average density of Partial envelope Breakpoint data) for this -//! Analyzer. -// -double -Analyzer::hopTime( void ) const -{ - return m_hopTime; -} - -// --------------------------------------------------------------------------- -// sidelobeLevel -// --------------------------------------------------------------------------- -//! Return the sidelobe attenutation level for the Kaiser analysis window in -//! positive dB. Larger numbers (e.g. 90) give very good sidelobe -//! rejection but cause the window to be longer in time. Smaller numbers -//! (like 60) raise the level of the sidelobes, increasing the likelihood -//! of frequency-domain interference, but allow the window to be shorter -//! in time. -// -double -Analyzer::sidelobeLevel( void ) const -{ - return m_sidelobeLevel; -} - -// --------------------------------------------------------------------------- -// windowWidth -// --------------------------------------------------------------------------- -//! Return the frequency-domain main lobe width (measured between -//! zero-crossings) of the analysis window used by this Analyzer. -// -double -Analyzer::windowWidth( void ) const -{ - return m_windowWidth; -} - -// --------------------------------------------------------------------------- -// phaseCorrect -// --------------------------------------------------------------------------- -//! Return true if the phases and frequencies of the constructed -//! partials should be modified to be consistent at the end of the -//! analysis, and false otherwise. (Default is true.) -//! -//! \param TF is a flag indicating whether or not to construct -//! phase-corrected Partials -bool -Analyzer::phaseCorrect( void ) const -{ - return m_phaseCorrect; -} - -// -- parameter mutation -- - -#define VERIFY_ARG(func, test) \ - do { \ - if (!(test)) \ - Throw( Loris::InvalidArgument, #func ": " #test ); \ - } while (false) - - -// --------------------------------------------------------------------------- -// setAmpFloor -// --------------------------------------------------------------------------- -//! Set the amplitude floor (lowest detected spectral amplitude), in -//! (negative) dB, for this Analyzer. -//! -//! \param x is the new value of this parameter. -// -void -Analyzer::setAmpFloor( double x ) -{ - VERIFY_ARG( setAmpFloor, x < 0 ); - m_ampFloor = x; -} - - -// --------------------------------------------------------------------------- -// setCropTime -// --------------------------------------------------------------------------- -//! Set the crop time (maximum temporal displacement of a time- -//! frequency data point from the time-domain center of the analysis -//! window, beyond which data points are considered "unreliable") -//! for this Analyzer. -//! -//! \param x is the new value of this parameter. -// -void -Analyzer::setCropTime( double x ) -{ - VERIFY_ARG( setCropTime, x > 0 ); - // debugger << "Analyzer::setCropTime() is a deprecated member, and will be removed in a future Loris release." << endl; - m_cropTime = x; -} - -// --------------------------------------------------------------------------- -// setFreqDrift -// --------------------------------------------------------------------------- -//! Set the maximum allowable frequency difference between -//! consecutive Breakpoints in a Partial envelope for this Analyzer. -//! -//! \param x is the new value of this parameter. -// -void -Analyzer::setFreqDrift( double x ) -{ - VERIFY_ARG( setFreqDrift, x > 0 ); - m_freqDrift = x; -} - -// --------------------------------------------------------------------------- -// setFreqFloor -// --------------------------------------------------------------------------- -//! Set the frequency floor (minimum instantaneous Partial -//! frequency), in Hz, for this Analyzer. -//! -//! \param x is the new value of this parameter. -// -void -Analyzer::setFreqFloor( double x ) -{ - VERIFY_ARG( setFreqFloor, x >= 0 ); - m_freqFloor = x; -} - -// --------------------------------------------------------------------------- -// setFreqResolution (constant) -// --------------------------------------------------------------------------- -//! Set the frequency resolution (minimum instantaneous frequency -//! difference between Partials) for this Analyzer. (Does not cause -//! other parameters to be recomputed.) -//! -//! \param x is the new value of this parameter. -// -void -Analyzer::setFreqResolution( double x ) -{ - VERIFY_ARG( setFreqResolution, x > 0 ); - m_freqResolutionEnv.reset( new LinearEnvelope( x ) ); -} - -// --------------------------------------------------------------------------- -// setFreqResolution (envelope) -// --------------------------------------------------------------------------- -//! Set the time-varying frequency resolution (minimum instantaneous frequency -//! difference between Partials) for this Analyzer. (Does not cause -//! other parameters to be recomputed.) -//! -//! \param e is the envelope to copy for this parameter. -// -void -Analyzer::setFreqResolution( const Envelope & e ) -{ - // No mechanism exists to verify that the envelope never - // drops below zero, this can only be checked at analysis-time. - // VERIFY_ARG( setFreqResolution, x > 0 ); - m_freqResolutionEnv.reset( e.clone() ); -} - -// --------------------------------------------------------------------------- -// setSidelobeLevel -// --------------------------------------------------------------------------- -//! Set the sidelobe attenutation level for the Kaiser analysis window in -//! positive dB. Higher numbers (e.g. 90) give very good sidelobe -//! rejection but cause the window to be longer in time. Lower -//! numbers raise the level of the sidelobes, increasing the likelihood -//! of frequency-domain interference, but allow the window to be shorter -//! in time. -//! -//! \param x is the new value of this parameter. -// -void -Analyzer::setSidelobeLevel( double x ) -{ - VERIFY_ARG( setSidelobeLevel, x > 0 ); - m_sidelobeLevel = x; -} - -// --------------------------------------------------------------------------- -// setHopTime -// --------------------------------------------------------------------------- -//! Set the hop time (which corresponds approximately to the average -//! density of Partial envelope Breakpoint data) for this Analyzer. -//! -//! \param x is the new value of this parameter. -// -void -Analyzer::setHopTime( double x ) -{ - VERIFY_ARG( setHopTime, x > 0 ); - m_hopTime = x; -} - -// --------------------------------------------------------------------------- -// setWindowWidth -// --------------------------------------------------------------------------- -//! Set the frequency-domain main lobe width (measured between -//! zero-crossings) of the analysis window used by this Analyzer. -//! -//! \param x is the new value of this parameter. -// -void -Analyzer::setWindowWidth( double x ) -{ - VERIFY_ARG( setWindowWidth, x > 0 ); - m_windowWidth = x; -} - -// --------------------------------------------------------------------------- -// setPhaseCorrect -// --------------------------------------------------------------------------- -//! Indicate whether the phases and frequencies of the constructed -//! partials should be modified to be consistent at the end of the -//! analysis. (Default is true.) -//! -//! \param TF is a flag indicating whether or not to construct -//! phase-corrected Partials -void -Analyzer::setPhaseCorrect( bool TF ) -{ - m_phaseCorrect = TF; -} - -// -- bandwidth envelope specification -- - - -// --------------------------------------------------------------------------- -// storeResidueBandwidth -// --------------------------------------------------------------------------- -//! Construct Partial bandwidth envelopes during analysis -//! by associating residual energy in the spectrum (after -//! peak extraction) with the selected spectral peaks that -//! are used to construct Partials. -//! -//! \param regionWidth is the width (in Hz) of the bandwidth -//! association regions used by this process, must be positive. -//! If unspecified, a default value is used. -// -void -Analyzer::storeResidueBandwidth( double regionWidth ) -{ - VERIFY_ARG( storeResidueBandwidth, regionWidth > 0 ); - m_bwAssocParam = regionWidth; -} - -// --------------------------------------------------------------------------- -// storeConvergenceBandwidth -// --------------------------------------------------------------------------- -//! Construct Partial bandwidth envelopes during analysis -//! by storing the mixed derivative of short-time phase, -//! scaled and shifted so that a value of 0 corresponds -//! to a pure sinusoid, and a value of 1 corresponds to a -//! bandwidth-enhanced sinusoid with maximal energy spread -//! (minimum sinusoidal convergence). -//! -//! \param tolerance is the amount of range over which the -//! mixed derivative indicator should be allowed to drift away -//! from a pure sinusoid before saturating. This range is mapped -//! to bandwidth values on the range [0,1]. Must be positive and -//! not greater than 1. If unspecified, a default value is used. -// -void -Analyzer::storeConvergenceBandwidth( double tolerance ) -{ - if ( 1.0 < tolerance ) - { - // notify and scale, in Loris 1.5, tolerance was - // specified as a percent - notifier << "Analyzer::storeConvergenceBandwidth, conergence tolerance " - "should be positive and less than 1.0, scaling by 1/100" << endl; - tolerance *= 0.01; - } - - VERIFY_ARG( storeConvergenceBandwidth, - (tolerance > 0) && (tolerance <= 1) ); - - // store a negative value so that it can be - // identified when used: - m_bwAssocParam = -tolerance; -} - -// --------------------------------------------------------------------------- -// storeNoBandwidth -// --------------------------------------------------------------------------- -//! Disable bandwidth envelope construction. Bandwidth -//! will be zero for all Breakpoints in all Partials. -// -void -Analyzer::storeNoBandwidth( void ) -{ - m_bwAssocParam = 0; -} - -// --------------------------------------------------------------------------- -//! Return true if this Analyzer is configured to compute -//! bandwidth envelopes using the spectral residue after -//! peaks have been identified, and false otherwise. -// --------------------------------------------------------------------------- -bool -Analyzer::bandwidthIsResidue( void ) const -{ - return m_bwAssocParam > 0.; -} - -// --------------------------------------------------------------------------- -//! Return true if this Analyzer is configured to compute -//! bandwidth envelopes using the mixed derivative convergence -//! indicator, and false otherwise. -// --------------------------------------------------------------------------- -bool -Analyzer::bandwidthIsConvergence( void ) const -{ - return m_bwAssocParam < 0.; -} - - -// --------------------------------------------------------------------------- -//! Return the width (in Hz) of the Bandwidth Association regions -//! used by this Analyzer, only if the spectral residue method is -//! used to compute bandwidth envelopes. Return zero if the mixed -//! derivative method is used, or if no bandwidth is computed. -// --------------------------------------------------------------------------- -double -Analyzer::bwRegionWidth( void ) const -{ - if ( m_bwAssocParam > 0 ) - { - return m_bwAssocParam; - } - return 0; -} - -// --------------------------------------------------------------------------- -//! Return the mixed derivative convergence tolerance (percent) -//! only if the convergence indicator is used to compute -//! bandwidth envelopes. Return zero if the spectral residue -//! method is used or if no bandwidth is computed. -// --------------------------------------------------------------------------- -double -Analyzer::bwConvergenceTolerance( void ) const -{ - if ( m_bwAssocParam < 0 ) - { - return - m_bwAssocParam; - } - return 0; -} - - -// -- PartialList access -- - -// --------------------------------------------------------------------------- -// partials -// --------------------------------------------------------------------------- -//! Return a mutable reference to this Analyzer's list of -//! analyzed Partials. -// -PartialList & -Analyzer::partials( void ) -{ - return m_partials; -} - -// --------------------------------------------------------------------------- -// partials -// --------------------------------------------------------------------------- -//! Return an immutable (const) reference to this Analyzer's -//! list of analyzed Partials. -// -const PartialList & -Analyzer::partials( void ) const -{ - return m_partials; -} - -// --------------------------------------------------------------------------- -// buildFundamentalEnv -// --------------------------------------------------------------------------- -//! Specify parameters for constructing a fundamental frequency -//! envelope for the analyzed sound during analysis. The fundamental -//! frequency estimate can be accessed by fundamentalEnv() after the -//! analysis is complete. -//! -//! \param fmin is the lower bound on the fundamental frequency estimate -//! \param fmax is the upper bound on the fundamental frequency estimate -//! \param threshDb is the lower bound on the amplitude of a spectral peak -//! that will constribute to the fundamental frequency estimate (very -//! low amplitude peaks tend to have less reliable frequency estimates). -//! Default is -60 dB. -//! \param threshHz is the upper bound on the frequency of a spectral -//! peak that will constribute to the fundamental frequency estimate. -//! Default is 8 kHz. -// -void Analyzer::buildFundamentalEnv( double fmin, double fmax, - double threshDb, double threshHz ) -{ - m_f0Builder.reset( - new FundamentalBuilder( fmin, fmax, threshDb, threshHz ) ); -} - -// --------------------------------------------------------------------------- -// fundamentalEnv -// --------------------------------------------------------------------------- -//! Return the fundamental frequency estimate envelope constructed -//! during the most recent analysis performed by this Analyzer. -//! Will be empty unless buildFundamentalEnv was invoked to enable the -//! construction of this envelope during analysis. -// -const LinearEnvelope & -Analyzer::fundamentalEnv( void ) const -{ - return m_f0Builder->envelope(); -} - - -// --------------------------------------------------------------------------- -// ampEnv -// --------------------------------------------------------------------------- -//! Return the overall amplitude estimate envelope constructed -//! during the most recent analysis performed by this Analyzer. -//! Will be empty unless buildAmpEnv was invoked to enable the -//! construction of this envelope during analysis. -// -const LinearEnvelope & -Analyzer::ampEnv( void ) const -{ - return m_ampEnvBuilder->envelope(); -} - -// -- private helpers -- - -// --------------------------------------------------------------------------- -// can_mask -// --------------------------------------------------------------------------- -// functor used for identying peaks that are too close -// in frequency to another louder peak: -struct can_mask -{ - // masking occurs if any (louder) peak falls - // in the frequency range delimited by fmin and fmax: - bool operator()( const SpectralPeak & v ) const - { - return ( v.frequency() > _fmin ) && - ( v.frequency() < _fmax ); - } - - // constructor: - can_mask( double x, double y ) : - _fmin( x ), _fmax( y ) - { if (x>y) std::swap(x,y); } - - // bounds: -private: - double _fmin, _fmax; -}; - -// --------------------------------------------------------------------------- -// negative_time -// --------------------------------------------------------------------------- -// functor used to identify peaks that have reassigned times -// before 0: -struct negative_time -{ - // negative times occur when the reassigned time - // plus the current frame time is less than 0: - bool operator()( const Peaks::value_type & v ) const - { - return 0 > ( v.time() + _frameTime ); - } - - // constructor: - negative_time( double t ) : - _frameTime( t ) {} - - // bounds: -private: - double _frameTime; - -}; - - -// --------------------------------------------------------------------------- -// thinPeaks (HELPER) -// --------------------------------------------------------------------------- -// Reject peaks that are too quiet (low amplitude). Peaks that are retained, -// but are quiet enough to be in the specified fadeRange should be faded. -// Peaks having negative times are also rejected. -// -// This is exactly the same as the basic peak selection strategy, there -// is no tracking here. -// -// Rejected peaks are placed at the end of the peak collection. -// Return the first position in the collection containing a rejected peak, -// or the end of the collection if no peaks are rejected. -// -// This used to be part of SpectralPeakSelector, but it really had no place -// there. It _should_ remove the rejected peaks, but for now, those are needed -// by the bandwidth association strategy. -// -Peaks::iterator -Analyzer::thinPeaks( Peaks & peaks, double frameTime ) -{ - const double ampFloordB = m_ampFloor; - - // fade quiet peaks out over 10 dB: - const double fadeRangedB = 10.0; - - // compute absolute magnitude thresholds: - const double threshold = std::pow( 10., 0.05 * ampFloordB ); - const double beginFade = std::pow( 10., 0.05 * (ampFloordB+fadeRangedB) ); - - // louder peaks are preferred, so consider them - // in order of louder magnitude: - std::sort( peaks.begin(), peaks.end(), SpectralPeak::sort_greater_amplitude ); - - // negative times are not real, but still might represent - // a noisy part of the spectrum... - Peaks::iterator bogusTimes = - std::remove_if( peaks.begin(), peaks.end(), negative_time( frameTime ) ); - - // ...get rid of them anyway - peaks.erase( bogusTimes, peaks.end() ); - bogusTimes = peaks.end(); - - - Peaks::iterator it = peaks.begin(); - Peaks::iterator beginRejected = it; - - const double freqResolution = - std::max( m_freqResolutionEnv->valueAt( frameTime ), 0.0 ); - - - while ( it != peaks.end() ) - { - SpectralPeak & pk = *it; - - // keep this peak if it is loud enough and not - // too near in frequency to a louder one: - double lower = pk.frequency() - freqResolution; - double upper = pk.frequency() + freqResolution; - if ( pk.amplitude() > threshold && - beginRejected == std::find_if( peaks.begin(), beginRejected, can_mask(lower, upper) ) ) - { - // this peak is a keeper, fade its - // amplitude if it is too quiet: - if ( pk.amplitude() < beginFade ) - { - double alpha = (beginFade - pk.amplitude())/(beginFade - threshold); - pk.setAmplitude( pk.amplitude() * (1. - alpha) ); - } - - // keep retained peaks at the front of the collection: - if ( it != beginRejected ) - { - std::swap( *it, *beginRejected ); - } - ++beginRejected; - } - ++it; - } - - // debugger << "thinPeaks retained " << std::distance( peaks.begin(), beginRejected ) << endl; - - // remove rejected Breakpoints: - //peaks.erase( beginRejected, peaks.end() ); - - return beginRejected; -} - -// --------------------------------------------------------------------------- -// fixBandwidth (HELPER) -// --------------------------------------------------------------------------- -// Fix the bandwidth value stored in the specified Peaks. -// This function is invoked if the spectral residue method is -// not used to compute bandwidth (that method overwrites the -// bandwidth already). If the convergence method is used to -// compute bandwidth, the appropriate scaling is applied -// to the stored mixed phase derivative. Otherwise, the -// Peak bandwidth is set to zero. -// -// The convergence value is on the range [0,1], 0 for a sinusoid, -// and 1 for an impulse. If convergence tolerance is specified (as -// a negative value in m_bwAssocParam), it should be positive and -// less than 1, and specifies the convergence value that is to -// correspond to bandwidth equal to 1.0. This is achieved by scaling -// the convergence by the inverse of the tolerance, and saturating -// at 1.0. -void Analyzer::fixBandwidth( Peaks & peaks ) -{ - - if ( m_bwAssocParam < 0 ) - { - double scale = 1.0 / (- m_bwAssocParam); - // m_bwAssocParam stores negative tolerance - - for ( Peaks::iterator it = peaks.begin(); it != peaks.end(); ++it ) - { - SpectralPeak & pk = *it; - pk.setBandwidth( std::min( 1.0, scale * pk.bandwidth() ) ); - } - } - else if ( m_bwAssocParam == 0 ) - { - for ( Peaks::iterator it = peaks.begin(); it != peaks.end(); ++it ) - { - SpectralPeak & pk = *it; - pk.setBandwidth( 0 ); - } - } -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Analyzer.h b/loris_library/Source/src/Analyzer.h deleted file mode 100644 index 17b36ed..0000000 --- a/loris_library/Source/src/Analyzer.h +++ /dev/null @@ -1,623 +0,0 @@ -#ifndef INCLUDE_ANALYZER_H -#define INCLUDE_ANALYZER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Analyzer.h - * - * Definition of class Loris::Analyzer. - * - * Kelly Fitz, 5 Dec 99 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include -#include -#include "../ThreadController.h" -#include "LinearEnvelope.h" -#include "Partial.h" -#include "PartialList.h" -// #include "SpectralPeaks.h" - -// begin namespace -namespace Loris { - -class Envelope; -class LinearEnvelopeBuilder; -// class Peaks; -// class Peaks::iterator; -// oooo, this is nasty, need to fix it! -class SpectralPeak; -typedef std::vector< SpectralPeak > Peaks; - -// --------------------------------------------------------------------------- -// class Analyzer -// -//! Class Analyzer represents a configuration of parameters for -//! performing Reassigned Bandwidth-Enhanced Additive Analysis -//! of sampled sounds. The analysis process yields a collection -//! of Partials, each having a trio of synchronous, non-uniformly- -//! sampled breakpoint envelopes representing the time-varying -//! frequency, amplitude, and noisiness of a single bandwidth- -//! enhanced sinusoid. These Partials are accumulated in the -//! Analyzer. -//! -//! The core analysis parameter is the frequency resolution, the -//! minimum instantaneous frequency spacing between partials. Most -//! other parameters are initially configured according to this -//! parameter (and the analysis window width, if specified). -//! Subsequent parameter mutations are independent. -//! -//! Bandwidth enhancement: -//! Two different strategies are available for computing bandwidth -//! (or noisiness) envelope: -//! -//! One strategy is to construct bandwidth envelopes during analysis -//! by associating residual energy in the spectrum (after peak -//! extraction) with the selected spectral peaks that are used -//! to construct Partials. This is the original bandwidth enhancement -//! algorithm, and bandwidth envelopes constructed in this way may -//! be suitable for use in bandwidth-enhanced synthesis. -//! -//! Another stategy is to construct bandwidth envelopes during -//! analysis by storing the mixed derivative of short-time phase, -//! scaled and shifted so that a value of 0 corresponds -//! to a pure sinusoid, and a value of 1 corresponds to a -//! bandwidth-enhanced sinusoid with maximal energy spread -//! (minimum convergence in frequency). These bandwidth envelopes -//! are not suitable for bandwidth-enhanced synthesis, be sure -//! to set the bandwidth to 0, or to disable bandwidth enhancement -//! before rendering. -//! -//! The Analyzer may be configured to use either of these two -//! strategies for bandwidth-enhanced analysis, or to construct -//! no bandwidth envelopes at all. If unspecified, the default -//! Analyzer configuration uses spectral residue to construct -//! bandwidth envelopes. -//! -//! \sa storeResidueBandwidth, storeConvergenceBandwidth, storeNoBandwidth -//! -//! For more information about Reassigned Bandwidth-Enhanced -//! Analysis and the Reassigned Bandwidth-Enhanced Additive Sound -//! Model, refer to the Loris website: www.cerlsoundgroup.org/Loris/. -// -class Analyzer -{ -// -- public interface -- -public: - -// -- construction -- - - //! Construct a new Analyzer configured with the given - //! frequency resolution (minimum instantaneous frequency - //! difference between Partials). All other Analyzer parameters - //! are computed from the specified frequency resolution. - //! - //! \param resolutionHz is the frequency resolution in Hz. - explicit Analyzer( double resolutionHz ); - - //! Construct a new Analyzer configured with the given - //! frequency resolution (minimum instantaneous frequency - //! difference between Partials) and analysis window width - //! (main lobe, zero-to-zero). All other Analyzer parameters - //! are computed from the specified resolution and window width. - //! - //! \param resolutionHz is the frequency resolution in Hz. - //! \param windowWidthHz is the main lobe width of the Kaiser - //! analysis window in Hz. - Analyzer( double resolutionHz, double windowWidthHz ); - - //! Construct a new Analyzer configured with the given time-varying - //! frequency resolution (minimum instantaneous frequency - //! difference between Partials) and analysis window width - //! (main lobe, zero-to-zero). All other Analyzer parameters - //! are computed from the specified resolution and window width. - //! - //! \param resolutionHz is the frequency resolution in Hz. - //! \param windowWidthHz is the main lobe width of the Kaiser - //! analysis window in Hz. - Analyzer( const Envelope & resolutionEnv, double windowWidthHz ); - - //! Construct a new Analyzer having identical - //! parameter configuration to another Analyzer. - //! The list of collected Partials is not copied. - //! - //! \param other is the Analyzer to copy. - Analyzer( const Analyzer & other ); - - //! Destroy this Analyzer. - ~Analyzer( void ); - - //! Construct a new Analyzer having identical - //! parameter configuration to another Analyzer. - //! The list of collected Partials is not copied. - //! - //! \param rhs is the Analyzer to copy. - Analyzer & operator=( const Analyzer & rhs ); - -// -- configuration -- - - //! Configure this Analyzer with the given frequency resolution - //! (minimum instantaneous frequency difference between Partials, - //! in Hz). All other Analyzer parameters are (re-)computed from the - //! frequency resolution, including the window width, which is - //! twice the resolution. - //! - //! \param resolutionHz is the frequency resolution in Hz. - void configure( double resolutionHz ); - - //! Configure this Analyzer with the given frequency resolution - //! (minimum instantaneous frequency difference between Partials) - //! and analysis window width (main lobe, zero-to-zero, in Hz). - //! All other Analyzer parameters are (re-)computed from the - //! frequency resolution and window width. - //! - //! \param resolutionHz is the frequency resolution in Hz. - //! \param windowWidthHz is the main lobe width of the Kaiser - //! analysis window in Hz. - //! - //! There are three categories of analysis parameters: - //! - the resolution, and params that are usually related to (or - //! identical to) the resolution (frequency floor and drift) - //! - the window width and params that are usually related to (or - //! identical to) the window width (hop and crop times) - //! - independent parameters (bw region width and amp floor) - void configure( double resolutionHz, double windowWidthHz ); - - //! Configure this Analyzer with the given time-varying frequency resolution - //! (minimum instantaneous frequency difference between Partials) - //! and analysis window width (main lobe, zero-to-zero, in Hz). - //! All other Analyzer parameters are (re-)computed from the - //! frequency resolution and window width. - //! - //! \param resolutionEnv is the time-varying frequency resolution - //! in Hz. - //! \param windowWidthHz is the main lobe width of the Kaiser - //! analysis window in Hz. - //! - //! There are three categories of analysis parameters: - //! - the resolution, and params that are usually related to (or - //! identical to) the resolution (frequency floor and drift) - //! - the window width and params that are usually related to (or - //! identical to) the window width (hop and crop times) - //! - independent parameters (bw region width and amp floor) - // - void configure( const Envelope & resolutionEnv, double windowWidthHz ); - -// -- analysis -- - - //! Analyze a vector of (mono) samples at the given sample rate - //! (in Hz) and store the extracted Partials in the Analyzer's - //! PartialList (std::list of Partials). - //! - //! \param vec is a vector of floating point samples - //! \param srate is the sample rate of the samples in the vector - void analyze( const std::vector & vec, double srate ); - - //! Analyze a range of (mono) samples at the given sample rate - //! (in Hz) and store the extracted Partials in the Analyzer's - //! PartialList (std::list of Partials). - //! - //! \param bufBegin is a pointer to a buffer of floating point samples - //! \param bufEnd is (one-past) the end of a buffer of floating point - //! samples - //! \param srate is the sample rate of the samples in the buffer - void analyze( const double * bufBegin, const double * bufEnd, double srate ); - -// -- tracking analysis -- - - //! Analyze a vector of (mono) samples at the given sample rate - //! (in Hz) and store the extracted Partials in the Analyzer's - //! PartialList (std::list of Partials). Use the specified envelope - //! as a frequency reference for Partial tracking. - //! - //! \param vec is a vector of floating point samples - //! \param srate is the sample rate of the samples in the vector - //! \param reference is an Envelope having the approximate - //! frequency contour expected of the resulting Partials. - void analyze( const std::vector & vec, double srate, - const Envelope & reference ); - - //! Analyze a range of (mono) samples at the given sample rate - //! (in Hz) and store the extracted Partials in the Analyzer's - //! PartialList (std::list of Partials). Use the specified envelope - //! as a frequency reference for Partial tracking. - //! - //! \param bufBegin is a pointer to a buffer of floating point samples - //! \param bufEnd is (one-past) the end of a buffer of floating point - //! samples - //! \param srate is the sample rate of the samples in the buffer - //! \param reference is an Envelope having the approximate - //! frequency contour expected of the resulting Partials. - void analyze( const double * bufBegin, const double * bufEnd, double srate, - const Envelope & reference ); - -// -- parameter access -- - - //! Return the amplitude floor (lowest detected spectral amplitude), - //! in (negative) dB, for this Analyzer. - double ampFloor( void ) const; - - //! Return the crop time (maximum temporal displacement of a time- - //! frequency data point from the time-domain center of the analysis - //! window, beyond which data points are considered "unreliable") - //! for this Analyzer. - double cropTime( void ) const; - - //! Return the maximum allowable frequency difference between - //! consecutive Breakpoints in a Partial envelope for this Analyzer. - double freqDrift( void ) const; - - //! Return the frequency floor (minimum instantaneous Partial - //! frequency), in Hz, for this Analyzer. - double freqFloor( void ) const; - - //! Return the frequency resolution (minimum instantaneous frequency - //! difference between Partials) for this Analyzer at the specified - //! time in seconds. If no time is specified, then the initial resolution - //! (at 0 seconds) is returned. - //! - //! \param time is the time in seconds at which to evaluate the - //! frequency resolution - double freqResolution( double time = 0.0 ) const; - - //! Return the hop time (which corresponds approximately to the - //! average density of Partial envelope Breakpoint data) for this - //! Analyzer. - double hopTime( void ) const; - - //! Return the sidelobe attenutation level for the Kaiser analysis window in - //! positive dB. Larger numbers (e.g. 90) give very good sidelobe - //! rejection but cause the window to be longer in time. Smaller numbers - //! (like 60) raise the level of the sidelobes, increasing the likelihood - //! of frequency-domain interference, but allow the window to be shorter - //! in time. - double sidelobeLevel( void ) const; - - //! Return the frequency-domain main lobe width (measured between - //! zero-crossings) of the analysis window used by this Analyzer. - double windowWidth( void ) const; - - //! Return true if the phases and frequencies of the constructed - //! partials should be modified to be consistent at the end of the - //! analysis, and false otherwise. (Default is true.) - bool phaseCorrect( void ) const; - - -// -- parameter mutation -- - - //! Set the amplitude floor (lowest detected spectral amplitude), in - //! (negative) dB, for this Analyzer. - //! - //! \param x is the new value of this parameter. - void setAmpFloor( double x ); - - //! Set the crop time (maximum temporal displacement of a time- - //! frequency data point from the time-domain center of the analysis - //! window, beyond which data points are considered "unreliable") - //! for this Analyzer. - //! - //! \param x is the new value of this parameter. - void setCropTime( double x ); - - //! Set the maximum allowable frequency difference between - //! consecutive Breakpoints in a Partial envelope for this Analyzer. - //! - //! \param x is the new value of this parameter. - void setFreqDrift( double x ); - - //! Set the frequency floor (minimum instantaneous Partial - //! frequency), in Hz, for this Analyzer. - //! - //! \param x is the new value of this parameter. - void setFreqFloor( double x ); - - //! Set the frequency resolution (minimum instantaneous frequency - //! difference between Partials) for this Analyzer. (Does not cause - //! other parameters to be recomputed.) - //! - //! \param x is the new value of this parameter. - void setFreqResolution( double x ); - - //! Set the time-varying frequency resolution (minimum instantaneous frequency - //! difference between Partials) for this Analyzer. (Does not cause - //! other parameters to be recomputed.) - //! - //! \param e is the envelope to copy for this parameter. - void setFreqResolution( const Envelope & e ); - - //! Set the hop time (which corresponds approximately to the average - //! density of Partial envelope Breakpoint data) for this Analyzer. - //! - //! \param x is the new value of this parameter. - void setHopTime( double x ); - - //! Set the sidelobe attenutation level for the Kaiser analysis window in - //! positive dB. More negative numbers (e.g. -90) give very good sidelobe - //! rejection but cause the window to be longer in time. Less negative - //! numbers raise the level of the sidelobes, increasing the likelihood - //! of frequency-domain interference, but allow the window to be shorter - //! in time. - //! - //! \param x is the new value of this parameter. - void setSidelobeLevel( double x ); - - //! Set the frequency-domain main lobe width (measured between - //! zero-crossings) of the analysis window used by this Analyzer. - //! - //! \param x is the new value of this parameter. - void setWindowWidth( double x ); - - //! Indicate whether the phases and frequencies of the constructed - //! partials should be modified to be consistent at the end of the - //! analysis. (Default is true.) - //! - //! \param TF is a flag indicating whether or not to construct - //! phase-corrected Partials - void setPhaseCorrect( bool TF = true ); - - -// -- bandwidth envelope specification -- - - enum { Default_ResidueBandwidth_RegionWidth = 2000, - Default_ConvergenceBandwidth_TolerancePct = 10 }; - - //! Construct Partial bandwidth envelopes during analysis - //! by associating residual energy in the spectrum (after - //! peak extraction) with the selected spectral peaks that - //! are used to construct Partials. - //! - //! This is the default bandwidth-enhancement strategy. - //! - //! \param regionWidth is the width (in Hz) of the bandwidth - //! association regions used by this process, must be positive. - //! If unspecified, a default value is used. - void storeResidueBandwidth( double regionWidth = Default_ResidueBandwidth_RegionWidth ); - - //! Construct Partial bandwidth envelopes during analysis - //! by storing the mixed derivative of short-time phase, - //! scaled and shifted so that a value of 0 corresponds - //! to a pure sinusoid, and a value of 1 corresponds to a - //! bandwidth-enhanced sinusoid with maximal energy spread - //! (minimum sinusoidal convergence). - //! - //! \param tolerance is the amount of range over which the - //! mixed derivative indicator should be allowed to drift away - //! from a pure sinusoid before saturating. This range is mapped - //! to bandwidth values on the range [0,1]. Must be positive and - //! not greater than 1. If unspecified, a default value is used. - void storeConvergenceBandwidth( double tolerancePct = - 0.01 * (double)Default_ConvergenceBandwidth_TolerancePct ); - - //! Disable bandwidth envelope construction. Bandwidth - //! will be zero for all Breakpoints in all Partials. - void storeNoBandwidth( void ); - - //! Return true if this Analyzer is configured to compute - //! bandwidth envelopes using the spectral residue after - //! peaks have been identified, and false otherwise. - bool bandwidthIsResidue( void ) const; - - //! Return true if this Analyzer is configured to compute - //! bandwidth envelopes using the mixed derivative convergence - //! indicator, and false otherwise. - bool bandwidthIsConvergence( void ) const; - - //! Return the width (in Hz) of the Bandwidth Association regions - //! used by this Analyzer, only if the spectral residue method is - //! used to compute bandwidth envelopes. Return zero if the mixed - //! derivative method is used, or if no bandwidth is computed. - double bwRegionWidth( void ) const; - - //! Return the mixed derivative convergence tolerance (percent) - //! only if the convergence indicator is used to compute - //! bandwidth envelopes. Return zero if the spectral residue - //! method is used or if no bandwidth is computed. - double bwConvergenceTolerance( void ) const; - - //! Return true if bandwidth envelopes are to be constructed - //! by any means, that is, if either bandwidthIsResidue() or - //! bandwidthIsConvergence() are true. Otherwise, return - //! false. - bool associateBandwidth( void ) const - { return bandwidthIsResidue() || bandwidthIsConvergence(); } - - //! Deprecated, use storeResidueBandwidth or storeNoBandwidth instead. - void setBwRegionWidth( double x ) - { - if ( x != 0 ) - { - storeResidueBandwidth( x ); - } - else - { - storeNoBandwidth(); - } - } - - -// -- PartialList access -- - - //! Return a mutable reference to this Analyzer's list of - //! analyzed Partials. - PartialList & partials( void ); - - //! Return an immutable (const) reference to this Analyzer's - //! list of analyzed Partials. - const PartialList & partials( void ) const; - -// -- envelope access -- - - enum { Default_FundamentalEnv_ThreshDb = -60, - Default_FundamentalEnv_ThreshHz = 8000 }; - - //! Specify parameters for constructing a fundamental frequency - //! envelope for the analyzed sound during analysis. The fundamental - //! frequency estimate can be accessed by fundamentalEnv() after the - //! analysis is complete. - //! - //! By default, a fundamental envelope is estimated during analysis - //! between the frequency resolution and 1.5 times the resolution. - //! - //! \param fmin is the lower bound on the fundamental frequency estimate - //! \param fmax is the upper bound on the fundamental frequency estimate - //! \param threshDb is the lower bound on the amplitude of a spectral peak - //! that will constribute to the fundamental frequency estimate (very - //! low amplitude peaks tend to have less reliable frequency estimates). - //! Default is -60 dB. - //! \param threshHz is the upper bound on the frequency of a spectral - //! peak that will constribute to the fundamental frequency estimate. - //! Default is 8 kHz. - void buildFundamentalEnv( double fmin, double fmax, - double threshDb = Default_FundamentalEnv_ThreshDb, - double threshHz = Default_FundamentalEnv_ThreshHz ); - - - //! Return the fundamental frequency estimate envelope constructed - //! during the most recent analysis performed by this Analyzer. - //! - //! By default, a fundamental envelope is estimated during analysis - //! between the frequency resolution and 1.5 times the resolution. - const LinearEnvelope & fundamentalEnv( void ) const; - - //! Return the overall amplitude estimate envelope constructed - //! during the most recent analysis performed by this Analyzer. - const LinearEnvelope & ampEnv( void ) const; - - -// -- legacy support -- - - // Fundamental and amplitude envelopes are always constructed during - // analysis, these members do nothing, and are retained for backwards - // compatibility. - void buildAmpEnv( bool TF = true ) { TF = TF; } - void buildFundamentalEnv( bool TF = true ) { TF = TF; } - -// -- private member variables -- - - hise::ThreadController* threadController = nullptr; - -private: - - std::auto_ptr< Envelope > m_freqResolutionEnv; - //! in Hz, minimum instantaneous frequency distance; - //! this is the core parameter, others are, by default, - //! computed from this one - - double m_ampFloor; //! dB, relative to full amplitude sine wave, absolute - //! amplitude threshold (negative) - - double m_windowWidth; //! in Hz, width of main lobe; this might be more - //! conveniently presented as window length, but - //! the main lobe width more explicitly highlights - //! the critical interaction with resolution - - // std::auto_ptr< Envelope > m_freqFloorEnv; - double m_freqFloor; //! lowest frequency (Hz) component extracted - //! in spectral analysis - - double m_freqDrift; //! the maximum frequency (Hz) difference between two - //! consecutive Breakpoints that will be linked to - //! form a Partial - - double m_hopTime; //! in seconds, time between analysis windows in - //! successive spectral analyses - - double m_cropTime; //! in seconds, maximum time correction for a spectral - //! component to be considered reliable, and to be eligible - //! for extraction and for Breakpoint formation - - double m_bwAssocParam; //! formerly, width in Hz of overlapping bandwidth - //! association regions, or zero if bandwidth association - //! is disabled, now a catch-all bandwidth association - //! parameter that, if negative, indicates the tolerance (%) - //! level used to construct bandwidth envelopes from the - //! mixed phase derivative indicator - - double m_sidelobeLevel; //! sidelobe attenutation level for the Kaiser analysis - //! window, in positive dB - - bool m_phaseCorrect; //! flag indicating that phases/frequencies should be - //! made consistent at the end of the analysis - - PartialList m_partials; //! collect Partials here - - //! builder object for constructing a fundamental frequency - //! estimate during analysis - std::auto_ptr< LinearEnvelopeBuilder > m_f0Builder; - - //! builder object for constructing an amplitude - //! estimate during analysis - std::auto_ptr< LinearEnvelopeBuilder > m_ampEnvBuilder; - -// -- private auxiliary functions -- -// future development -/* - - // These members make up the sequence of operations in an - // analysis. If analysis were ever to be made into a - // template method, these would be the operations that - // derived classes could override. Or each of these could - // be represented by a strategy class. - - //! Compute the spectrum of the next sequence of samples. - void computeSpectrum( void ); - - //! Identify and select the spectral components that will be - //! used to form Partials. - void selectPeaks( void ); - - //! Compute the bandwidth coefficients for the Breakpoints - //! that are going to be used to form Partials. - void associateBandwidth( void ); - - //! Construct Partials from extracted spectral components. - //! Partials are built up frame by frame by appending - //! Breakpoints to Partials under construction, and giving - //! birth to new Partials using unmatched Peaks. - void formPartials( Peaks & peaks ); -*/ - // Reject peaks that are too close in frequency to a louder peak that is - // being retained, and peaks that are too quiet. Peaks that are retained, - // but are quiet enough to be in the specified fadeRange should be faded. - // - // Rejected peaks are placed at the end of the peak collection. - // Return the first position in the collection containing a rejected peak, - // or the end of the collection if no peaks are rejected. - Peaks::iterator thinPeaks( Peaks & peaks, double frameTime ); - - // Fix the bandwidth value stored in the specified Peaks. - // This function is invoked if the spectral residue method is - // not used to compute bandwidth (that method overwrites the - // bandwidth already). If the convergence method is used to - // compute bandwidth, the appropriate scaling is applied - // to the stored mixed phase derivative. Otherwise, the - // Peak bandwidth is set to zero. - void fixBandwidth( Peaks & peaks ); - -}; // end of class Analyzer - -} // end of namespace Loris - -#endif /* ndef INCLUDE_ANALYZER_H */ diff --git a/loris_library/Source/src/AssociateBandwidth.cpp b/loris_library/Source/src/AssociateBandwidth.cpp deleted file mode 100644 index e72c52f..0000000 --- a/loris_library/Source/src/AssociateBandwidth.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * AssociateBandwidth.C - * - * Implementation of a class representing a policy for associating noise - * (bandwidth) energy with reassigned spectral peaks to be used in - * Partial formation. - * - * Kelly Fitz, 20 Jan 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "AssociateBandwidth.h" -#include "Breakpoint.h" -#include "BreakpointUtils.h" -#include "LorisExceptions.h" -#include "Notifier.h" -#include "SpectralPeaks.h" - -#include -#include - -using namespace Loris; - -// --------------------------------------------------------------------------- -// AssociateBandwidth constructor -// --------------------------------------------------------------------------- -// Association regions are centered on all integer bin frequencies, regionWidth -// is the total width (in Hz) of the overlapping bandwidth association regions, -// the region centers are spaced at half this width. -// -AssociateBandwidth::AssociateBandwidth( double regionWidth, double srate ) : - _regionRate( 0 ) -{ - if ( ! (regionWidth>0) ) - Throw( InvalidArgument, "The regionWidth must be greater than 0 Hz." ); - if ( ! (srate>0) ) - Throw( InvalidArgument, "The sample rate must be greater than 0 Hz." ); - - - _weights.resize( int(srate/regionWidth) ); - _surplus.resize( int(srate/regionWidth) ); - _regionRate = 2./regionWidth; -} - -// --------------------------------------------------------------------------- -// AssociateBandwidth destructor -// --------------------------------------------------------------------------- -// -AssociateBandwidth::~AssociateBandwidth( void ) -{ -} - -// --------------------------------------------------------------------------- -// binFrequency -// --------------------------------------------------------------------------- -// Compute the warped fractional bin/region frequency corresponding to -// freqHz. (_regionRate is the number of regions per hertz.) -// -// Once, we used bark frequency scale warping here, but there seems to be -// no reason to do so. The best results seem to be indistinguishable from -// plain 'ol 1k bins, and some results are much worse. -// -static double binFrequency( double freqHz, double regionRate ) -{ -//#define Use_Barks -#ifndef Use_Barks - return freqHz * regionRate; -#else - // Compute Bark frequency from Hertz. - // Got this formula for Bark frequency from Sciarraba's thesis. - // Ignore region rate when using barks - double tmp = std::atan( ( 0.001 / 7.5 ) * freqHz ); - return 13. * std::atan( 0.76 * 0.001 * freqHz ) + 3.5 * ( tmp * tmp ); -#endif - -} - -// --------------------------------------------------------------------------- -// findRegionBelow -// --------------------------------------------------------------------------- -// Return the index of the last region having center frequency less than -// or equal to freq, or -1 if no region is low enough. -// -// Note: the zeroeth region is centered at bin frequency 1 and tapers -// to zero at bin frequency 0! (when booger is 1.) -// -static int findRegionBelow( double binfreq, unsigned int howManyBins ) -{ - const double booger = 0.; - if ( binfreq < booger ) - { - return -1; - } - else - { - return int( std::min( std::floor(binfreq - booger), howManyBins - 1. ) ); - } -} - -// --------------------------------------------------------------------------- -// computeAlpha -// --------------------------------------------------------------------------- -// binfreq is a warped, fractional bin frequency, and bin frequencies -// are integers. Return the relative contribution of a component at -// binfreq to the bins (bw association regions) below and above -// binfreq. -// -static double computeAlpha( double binfreq, unsigned int howManyBins ) -{ - // everything above the center of the highest - // bin is lumped into that bin; i.e it does - // not taper off at higher frequencies: - if ( binfreq > howManyBins ) - { - return 0.; - } - else - { - return binfreq - std::floor( binfreq ); - } -} - -// --------------------------------------------------------------------------- -// distribute -// --------------------------------------------------------------------------- -// -static void distribute( double fractionalBin, double x, std::vector & regions ) -{ - // contribute x to two regions having center - // frequencies less and greater than freqHz: - int posBelow = findRegionBelow( fractionalBin, regions.size() ); - int posAbove = posBelow + 1; - - double alpha = computeAlpha( fractionalBin, regions.size() ); - - if ( posAbove < regions.size() ) - regions[posAbove] += alpha * x; - - if ( posBelow >= 0 ) - regions[posBelow] += (1. - alpha) * x; -} - -// --------------------------------------------------------------------------- -// computeNoiseEnergy -// --------------------------------------------------------------------------- -// Return the noise energy to be associated with a component at freqHz. -// _surplus contains the surplus spectral energy in each region, which is, -// by defintion, non-negative. -// -double -AssociateBandwidth::computeNoiseEnergy( double freq, double amp ) -{ - // don't mess with negative frequencies: - if ( freq < 0. ) - return 0.; - - // compute the fractional bin frequency - // corresponding to freqHz: - double bin = binFrequency( freq, _regionRate ); - - // contribute x to two regions having center - // frequencies less and greater than freqHz: - int posBelow = findRegionBelow( bin, _surplus.size() ); - int posAbove = posBelow + 1; - - double alpha = computeAlpha( bin, _surplus.size() ); - - double noise = 0.; - // Have to check for alpha == 0, because - // the weights will be zero (see computeAlpha()): - // (ignore lowest regions) - const int LowestRegion = 2; - /* - if ( posAbove < _surplus.size() && alpha != 0. && posAbove >= LowestRegion ) - noise += _surplus[posAbove] * alpha / _weights[posAbove]; - - if ( posBelow >= LowestRegion ) - noise += _surplus[posBelow] * (1. - alpha) / _weights[posBelow]; - */ - // new idea, weight Partials by amplitude: - if ( posAbove < _surplus.size() && alpha != 0. && posAbove >= LowestRegion ) - noise += _surplus[posAbove] * alpha * amp / _weights[posAbove]; - - if ( posBelow >= LowestRegion ) - noise += _surplus[posBelow] * (1. - alpha) * amp / _weights[posBelow]; - - return noise; -} - -// --------------------------------------------------------------------------- -// accumulateSinusoid -// --------------------------------------------------------------------------- -// Accumulate sinusoidal energy at frequency f and amplitude a. -// The amplitude isn't used for anything. -// -void -AssociateBandwidth::accumulateSinusoid( double freq, double amp ) -{ - // distribute weight at the peak frequency, - // don't mess with negative frequencies: - if ( freq > 0. ) - { - //distribute( binFrequency( freq, _regionRate ), 1., _weights ); - // new idea: weight Partials by amplitude: - distribute( binFrequency( freq, _regionRate ), amp, _weights ); - } -} - -// --------------------------------------------------------------------------- -// accumulateNoise -// --------------------------------------------------------------------------- -// Accumulate a rejected spectral peak as surplus (noise) energy. -// -void -AssociateBandwidth::accumulateNoise( double freq, double amp ) -{ - // compute energy contribution and distribute - // at frequency f, don't mess with negative - // frequencies: - if ( freq > 0. ) - { - distribute( binFrequency( freq, _regionRate ), amp * amp, _surplus ); - } -} - -// --------------------------------------------------------------------------- -// associate -// --------------------------------------------------------------------------- -// Associate bandwidth with a single SpectralPeak. -// -void -AssociateBandwidth::associate( SpectralPeak & pk ) -{ - pk.setBandwidth(0); - pk.addNoiseEnergy( computeNoiseEnergy( pk.frequency(), pk.amplitude() ) ); -} - -// --------------------------------------------------------------------------- -// reset -// --------------------------------------------------------------------------- -// This is called after each distribution of bandwidth energy. -// -void -AssociateBandwidth::reset( void ) -{ - std::fill( _weights.begin(), _weights.end(), 0. ); - std::fill( _surplus.begin(), _surplus.end(), 0. ); -} - -// --------------------------------------------------------------------------- -// associate -// --------------------------------------------------------------------------- -// Perform bandwidth association on a collection of reassigned spectral peaks -// or ridges. The range [begin, rejected) spans the Peaks selected to form -// Partials. The range [rejected, end) spans the Peaks that were found in -// the reassigned spectrum, but rejected as too weak or too close (in -// frequency) to another stronger Peak. -// -void -AssociateBandwidth::associateBandwidth( Peaks::iterator begin, // beginning of Peaks - Peaks::iterator rejected, // first rejected Peak - Peaks::iterator end ) // end of Peaks -{ - if ( begin == rejected ) - return; - - // accumulate retained Breakpoints as sinusoids, - for ( Peaks::iterator it = begin; it != rejected; ++it ) - { - accumulateSinusoid( it->frequency(), it->amplitude() ); - } - - // accumulate rejected breakpoints as noise: - for ( Peaks::iterator it = rejected; it != end; ++it ) - { - accumulateNoise( it->frequency(), it->amplitude() ); - } - - // associate bandwidth with each retained Breakpoint: - for ( Peaks::iterator it = begin; it != rejected; ++it ) - { - // sets bandwidth to zero, then calls addNoiseEnergy() - associate( *it ); - } - - // reset after association, yuk: - reset(); - -} diff --git a/loris_library/Source/src/AssociateBandwidth.h b/loris_library/Source/src/AssociateBandwidth.h deleted file mode 100644 index 475aeb0..0000000 --- a/loris_library/Source/src/AssociateBandwidth.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef INCLUDE_ASSOCIATEBANDWIDTH_H -#define INCLUDE_ASSOCIATEBANDWIDTH_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * AssociateBandwidth.h - * - * Definition of a class representing a policy for associating noise - * (bandwidth) energy with reassigned spectral peaks to be used in - * Partial formation. - * - * Kelly Fitz, 20 Jan 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "SpectralPeaks.h" - -#include - -// begin namespace -namespace Loris { - -class Breakpoint; - -// --------------------------------------------------------------------------- -// class AssociateBandwidth -// -// In the new strategy, Breakpoints are extracted and accumulated -// as sinusoids. Spectral peaks that are not extracted (don't exceed -// the amplitude floor) or are rejected for certain reasons, are -// accumulated diectly as noise (surplus). After all spectral peaks -// have been accumulated as noise or sinusoids, the noise is distributed -// as bandwidth. -// -class AssociateBandwidth -{ -// -- instance variables -- - std::vector< double > _weights; // weights vector for recording - // frequency distribution of retained - // sinusoids - std::vector< double > _surplus; // surplus (noise) energy vector for - // accumulating the distribution of - // spectral energy to be distributed - // as noise - - double _regionRate; // inverse of region center spacing - -// -- public interface -- -public: - // construction: - AssociateBandwidth( double regionWidth, double srate ); - ~AssociateBandwidth( void ); - - // Perform bandwidth association on a collection of reassigned spectral peaks - // or ridges. The range [begin, rejected) spans the Peaks selected to form - // Partials. The range [rejected, end) spans the Peaks that were found in - // the reassigned spectrum, but rejected as too weak or too close (in - // frequency) to another stronger Peak. - void associateBandwidth( Peaks::iterator begin, // beginning of Peaks - Peaks::iterator rejected, // first rejected Peak - Peaks::iterator end ); // end of Peaks - - -// -- private helpers -- -private: - double computeNoiseEnergy( double freq, double amp ); - - // These four formerly comprised the public interface - // to this policy, now they are all hidden behind a - // single call to associateBandwidth. - - // energy accumulation: - void accumulateNoise( double freq, double amp ); - void accumulateSinusoid( double freq, double amp ); - - // bandwidth assocation: - void associate( SpectralPeak & pk ); - - // call this to wipe out the accumulated energy to - // prepare for the next frame (yuk): - void reset( void ); - -}; // end of class AssociateBandwidth - -} // end of namespace Loris - -#endif /* ndef INCLUDE_ASSOCIATEBANDWIDTH_H */ diff --git a/loris_library/Source/src/BigEndian.cpp b/loris_library/Source/src/BigEndian.cpp deleted file mode 100644 index 515b010..0000000 --- a/loris_library/Source/src/BigEndian.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * BigEndian.C - * - * Implementation of wrappers for stream-based binary file i/o. - * - * Kelly Fitz, 23 May 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "BigEndian.h" -#include "LorisExceptions.h" -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// bigEndianSystem -// --------------------------------------------------------------------------- -// Return true is this is a big-endian system, false otherwise. -// -static bool bigEndianSystem( void ) -{ -#if defined(WORDS_BIGENDIAN) - return true; -#elif HAVE_CONFIG_H && !defined(WORDS_BIGENDIAN) - return false; -#else - static union { - int s ; - char c[sizeof(int)] ; - } x ; - bool ret = (x.s = 1, x.c[0] != 1) ? true : false; - - return ret; // x.c[0] != 1; -#endif -} - -// --------------------------------------------------------------------------- -// swapByteOrder -// --------------------------------------------------------------------------- -// -static void swapByteOrder( char * bytes, int n ) -{ - char * beg = bytes, * end = bytes + n - 1; - while ( beg < end ) { - char tmp = *end; - *end = *beg; - *beg = tmp; - - ++beg; - --end; - } -} - -// --------------------------------------------------------------------------- -// BigEndian read -// --------------------------------------------------------------------------- -// -std::istream & -BigEndian::read( std::istream & s, long howmany, int size, char * putemHere ) -{ - // read the bytes into data: - s.read( putemHere, howmany*size ); - - // check stream state: - if ( s ) - { - // if the stream is still in a good state, then - // the correct number of bytes must have been read: - Assert( s.gcount() == howmany*size ); - - // swap byte order if nec. - if ( ! bigEndianSystem() && size > 1 ) - { - for ( long i = 0; i < howmany; ++i ) - { - swapByteOrder( putemHere + (i*size), size ); - } - } - } - - return s; -} - -// --------------------------------------------------------------------------- -// BigEndian write -// --------------------------------------------------------------------------- -// -std::ostream & -BigEndian::write( std::ostream & s, long howmany, int size, const char * stuff ) -{ - // swap byte order if nec. - if ( ! bigEndianSystem() && size > 1 ) - { - // use a temporary vector to automate storage: - std::vector v( stuff, stuff + (howmany*size) ); - for ( long i = 0; i < howmany; ++i ) - { - swapByteOrder( & v[i*size], size ); - } - s.write( &v[0], howmany*size ); - } - else - { - // read the bytes into data: - s.write( stuff, howmany*size ); - } - - // check stream state: - if ( ! s.good() ) - Throw( FileIOException, "File write failed. " ); - - return s; -} - -} // end of namespace Loris - - diff --git a/loris_library/Source/src/BigEndian.h b/loris_library/Source/src/BigEndian.h deleted file mode 100644 index d4d70e8..0000000 --- a/loris_library/Source/src/BigEndian.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef INCLUDE_BIGENDIAN_H -#define INCLUDE_BIGENDIAN_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * BigEndian.h - * - * Definition of wrappers for stream-based binary file i/o. - * - * Kelly Fitz, 23 May 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class BigEndian -// -class BigEndian -{ -public: - static std::istream & read( std::istream & s, long howmany, int size, char * putemHere ); - static std::ostream & write( std::ostream & s, long howmany, int size, const char * stuff ); -}; // end of class BigEndian - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_BIGENDIAN_H */ diff --git a/loris_library/Source/src/Breakpoint.cpp b/loris_library/Source/src/Breakpoint.cpp deleted file mode 100644 index 4e5659f..0000000 --- a/loris_library/Source/src/Breakpoint.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Breakpoint.C - * - * Implementation of class Loris::Breakpoint. - * - * Kelly Fitz, 16 Aug 99 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Breakpoint.h" -#include "LorisExceptions.h" -#include - -// begin namespace -namespace Loris { - - -// - -// construction - -// --------------------------------------------------------------------------- -// Breakpoint default constructor -// --------------------------------------------------------------------------- -//! Construct a new Breakpoint with all parameters initialized to 0 -//! (needed for STL containability). -Breakpoint::Breakpoint( void ) : - _frequency( 0. ), - _amplitude( 0. ), - _bandwidth( 0. ), - _phase( 0. ) -{ -} - -// --------------------------------------------------------------------------- -// Breakpoint constructor -// --------------------------------------------------------------------------- -//! Construct a new Breakpoint with the specified parameters. -//! -//! \param f is the intial frequency. -//! \param a is the initial amplitude. -//! \param b is the initial bandwidth. -//! \param p is the initial phase, if specified (if unspecified, 0 -//! is assumed). -// -Breakpoint::Breakpoint( double f, double a, double b, double p ) : - _frequency( f ), - _amplitude( a ), - _bandwidth( b ), - _phase( p ) -{ -} - -// --------------------------------------------------------------------------- -// addNoiseEnergy -// --------------------------------------------------------------------------- -//! Add noise (bandwidth) energy to this Breakpoint by computing new -//! amplitude and bandwidth values. enoise may be negative, but -//! noise energy cannot be removed (negative energy added) in excess -//! of the current noise energy. -//! -//! \param enoise is the amount of noise energy to add to -//! this Breakpoint. -// -void -Breakpoint::addNoiseEnergy( double enoise ) -{ - // compute current energies: - double e = amplitude() * amplitude(); // current total energy - double n = e * bandwidth(); // current noise energy - - // Assert( e >= n ); - // could complain, but its recoverable, just fix it: - if ( e < n ) - { - e = n; - } - - // guard against divide-by-zero, and don't allow - // the sinusoidal energy to decrease: - if ( n + enoise > 0. ) - { - // if new noise energy is positive, total - // energy must also be positive: - // Assert( e + enoise > 0 ); - setBandwidth( (n + enoise) / (e + enoise) ); - setAmplitude( std::sqrt(e + enoise) ); - } - else - { - // if new noise energy is negative, leave - // all sinusoidal energy: - setBandwidth( 0. ); - setAmplitude( std::sqrt( e - n ) ); - } -} - -} // end of namespace Loris - - - - diff --git a/loris_library/Source/src/Breakpoint.h b/loris_library/Source/src/Breakpoint.h deleted file mode 100644 index 31123dd..0000000 --- a/loris_library/Source/src/Breakpoint.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef INCLUDE_BREAKPOINT_H -#define INCLUDE_BREAKPOINT_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Breakpoint.h - * - * Definition of class Loris::Breakpoint. - * - * Kelly Fitz, 16 Aug 99 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// class Breakpoint -// -//! Class Breakpoint represents a single breakpoint in the -//! Partial parameter (frequency, amplitude, bandwidth) envelope. -//! Instantaneous phase is also stored, but is only used at the onset of -//! a partial, or when it makes a transition from zero to nonzero amplitude. -//! -//! Loris Partials represent reassigned bandwidth-enhanced model components. -//! A Partial consists of a chain of Breakpoints describing the time-varying -//! frequency, amplitude, and bandwidth (noisiness) of the component. -//! For more information about Reassigned Bandwidth-Enhanced -//! Analysis and the Reassigned Bandwidth-Enhanced Additive Sound -//! Model, refer to the Loris website: -//! www.cerlsoundgroup.org/Loris/. -//! -//! Breakpoint is a leaf class, do not subclass. -// -class Breakpoint -{ -// -- instance variables -- - double _frequency; //! in Hertz - double _amplitude; //! absolute - double _bandwidth; //! fraction of total energy that is noise energy - double _phase; //! radians - -// -- public Breakpoint interface -- - -public: -// -- construction -- - - //! Construct a new Breakpoint with all parameters initialized to 0 - //! (needed for STL containability). - Breakpoint( void ); - - //! Construct a new Breakpoint with the specified parameters. - //! - //! \param f is the intial frequency. - //! \param a is the initial amplitude. - //! \param b is the initial bandwidth. - //! \param p is the initial phase, if specified (if unspecified, 0 - //! is assumed). - Breakpoint( double f, double a, double b, double p = 0. ); - - // (use compiler-generated destructor, copy, and assign) - -// -- access -- - //! Return the amplitude of this Breakpoint. - double amplitude( void ) const { return _amplitude; } - - //! Return the bandwidth (noisiness) coefficient of this Breakpoint. - double bandwidth( void ) const { return _bandwidth; } - - //! Return the frequency of this Breakpoint. - double frequency( void ) const { return _frequency; } - - //! Return the phase of this Breakpoint. - double phase( void ) const { return _phase; } - -// -- mutation -- - //! Set the amplitude of this Breakpoint. - //! - //! \param x is the new amplitude - void setAmplitude( double x ) { _amplitude = x; } - - //! Set the bandwidth (noisiness) coefficient of this Breakpoint. - //! - //! \param x is the new bandwidth - void setBandwidth( double x ) { _bandwidth = x; } - - //! Set the frequency of this Breakpoint. - //! - //! \param x is the new frequency. - void setFrequency( double x ) { _frequency = x; } - - //! Set the phase of this Breakpoint. - //! - //! \param x is the new phase. - void setPhase( double x ) { _phase = x; } - - //! Add noise (bandwidth) energy to this Breakpoint by computing new - //! amplitude and bandwidth values. enoise may be negative, but - //! noise energy cannot be removed (negative energy added) in excess - //! of the current noise energy. - //! - //! \param enoise is the amount of noise energy to add to - //! this Breakpoint. - void addNoiseEnergy( double enoise ); - -}; // end of class Breakpoint - -} // end of namespace Loris - -#endif /* ndef INCLUDE_BREAKPOINT_H */ diff --git a/loris_library/Source/src/BreakpointEnvelope.h b/loris_library/Source/src/BreakpointEnvelope.h deleted file mode 100644 index 383626a..0000000 --- a/loris_library/Source/src/BreakpointEnvelope.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef INCLUDE_BREAKPOINTENVELOPE_H -#define INCLUDE_BREAKPOINTENVELOPE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * BreakpointEnvelope.h - * - * Definition of class BreakpointEnvelope. - * This class has been renamed LinearEnvelope. The old - * name and header are preserved for compatibility. - * - * Kelly Fitz, 21 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "LinearEnvelope.h" - -// begin namespace -namespace Loris { - - typedef LinearEnvelope BreakpointEnvelope; - -} - -#endif /* ndef INCLUDE_BREAKPOINTENVELOPE_H */ diff --git a/loris_library/Source/src/BreakpointUtils.cpp b/loris_library/Source/src/BreakpointUtils.cpp deleted file mode 100644 index ea1ab68..0000000 --- a/loris_library/Source/src/BreakpointUtils.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * BreakpointUtils.C - * - * Out-of-line Breakpoint utility functions collected in namespace BreakpointUtils. - * - * Kelly Fitz, 19 June 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "BreakpointUtils.h" -#include "Breakpoint.h" - -#include -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// makeNullBefore -// --------------------------------------------------------------------------- -// Return a null (zero-amplitude) Breakpoint to preceed the specified -// Breakpoint, useful for fading in a Partial. -// -Breakpoint -BreakpointUtils::makeNullBefore( const Breakpoint & bp, double fadeTime ) -{ - Breakpoint ret( bp ); - // adjust phase - double dp = 2. * Pi * fadeTime * bp.frequency(); - ret.setPhase( std::fmod( bp.phase() - dp, 2. * Pi ) ); - ret.setAmplitude(0.); - ret.setBandwidth(0.); - - return ret; -} - -// --------------------------------------------------------------------------- -// makeNullAfter -// --------------------------------------------------------------------------- -// Return a null (zero-amplitude) Breakpoint to succeed the specified -// Breakpoint, useful for fading out a Partial. -// -Breakpoint -BreakpointUtils::makeNullAfter( const Breakpoint & bp, double fadeTime ) -{ - Breakpoint ret( bp ); - // adjust phase - double dp = 2. * Pi * fadeTime * bp.frequency(); - ret.setPhase( std::fmod( bp.phase() + dp, 2. * Pi ) ); - ret.setAmplitude(0.); - ret.setBandwidth(0.); - - return ret; -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/BreakpointUtils.h b/loris_library/Source/src/BreakpointUtils.h deleted file mode 100644 index 41fd106..0000000 --- a/loris_library/Source/src/BreakpointUtils.h +++ /dev/null @@ -1,217 +0,0 @@ -#ifndef INCLUDE_BREAKPOINTUTILS_H -#define INCLUDE_BREAKPOINTUTILS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * BreakpointUtils.h - * - * Breakpoint utility functions collected in namespace BreakpointUtils. - * - * Kelly Fitz, 6 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Breakpoint.h" -#include -#include - -// begin namespace -namespace Loris { - -namespace BreakpointUtils { - -// -- free functions -- - -// --------------------------------------------------------------------------- -// addNoiseEnergy -// --------------------------------------------------------------------------- -//! Add noise (bandwidth) energy to a Breakpoint by computing new -//! amplitude and bandwidth values. enoise may be negative, but -//! noise energy cannot be removed (negative energy added) in excess -//! of the current noise energy. -//! -//! \deprecated This operation is now part of the Breakpoint interface. -//! Use Breakpoint::addNoiseEnergy instead. -// -inline void addNoiseEnergy( Breakpoint & bp, double enoise ) -{ - bp.addNoiseEnergy(enoise); -} - -// --------------------------------------------------------------------------- -// makeNullBefore -// --------------------------------------------------------------------------- -//! Return a null (zero-amplitude) Breakpoint to preceed the specified -//! Breakpoint, useful for fading in a Partial. -//! -//! \param bp make a null Breakpoint to preceed this one -//! \param fadeTime the time (in seconds) by which the new null Breakpoint -//! should preceed bp -//! \return a new null Breakpoint, having zero amplitude, frequency equal -//! to that of bp, and phase computed back from that of bp -// -Breakpoint makeNullBefore( const Breakpoint & bp, double fadeTime ); // see BreakpointUtils.C - - -// --------------------------------------------------------------------------- -// addNoiseEnergy -// --------------------------------------------------------------------------- -//! Return a null (zero-amplitude) Breakpoint to succeed the specified -//! Breakpoint, useful for fading out a Partial. -//! -//! \param bp make a null Breakpoint to succeed this one -//! \param fadeTime the time (in seconds) by which the new null Breakpoint -//! should succeed bp -//! \return a new null Breakpoint, having zero amplitude, frequency equal -//! to that of bp, and phase computed forward from that of bp -// -Breakpoint makeNullAfter( const Breakpoint & bp, double fadeTime ); // see BreakpointUtils.C - -// -- predicates -- - -// --------------------------------------------------------------------------- -// isFrequencyBetween -// -//! Predicate functor returning true if its Breakpoint argument -//! has frequency between specified bounds, and false otherwise. -// -class isFrequencyBetween : - public std::unary_function< const Breakpoint, bool > -{ -public: - //! Return true if its Breakpoint argument has frequency - //! between specified bounds, and false otherwise. - bool operator()( const Breakpoint & b ) const - { - return (b.frequency() > _fmin) && - (b.frequency() < _fmax); - } - -// constructor: - - //! Construct a predicate functor, specifying two frequency bounds. - isFrequencyBetween( double x, double y ) : - _fmin( x ), _fmax( y ) - { - if (x>y) std::swap(x,y); - } - -// bounds: -private: - double _fmin, _fmax; -}; - -//! Old name for isFrequencyBetween. -//! \deprecated use isFrequencyBetween instead. -typedef isFrequencyBetween frequency_between; - -// --------------------------------------------------------------------------- -// isNonNull -// -//! Predicate functor returning true if a Breakpoint has non-zero -//! amplitude, false otherwise. -// -static bool isNonNull( const Breakpoint & bp ) -{ - return bp.amplitude() != 0.; -} - -// --------------------------------------------------------------------------- -// isNull -// -//! Predicate functor returning true if a Breakpoint has zero -//! amplitude, false otherwise. -// -static bool isNull( const Breakpoint & bp ) -{ - return ! isNonNull( bp ); -} - -// -- comparitors -- - -// --------------------------------------------------------------------------- -// compareFrequencyLess -// -//! Comparitor (binary) functor returning true if its first Breakpoint -//! argument has frequency less than that of its second Breakpoint argument, -//! and false otherwise. -// -class compareFrequencyLess : - public std::binary_function< const Breakpoint, const Breakpoint, bool > -{ -public: - //! Return true if its first Breakpoint argument has frequency less - //! than that of its second Breakpoint argument, and false otherwise. - bool operator()( const Breakpoint & lhs, const Breakpoint & rhs ) const - { return lhs.frequency() < rhs.frequency(); } -}; - -//! Old name for compareFrequencyLess. -//! \deprecated use compareFrequencyLess instead. -typedef compareFrequencyLess less_frequency; - -// --------------------------------------------------------------------------- -// compareAmplitudeGreater -// -//! Comparitor (binary) functor returning true if its first Breakpoint -//! argument has amplitude greater than that of its second Breakpoint argument, -//! and false otherwise. -// -class compareAmplitudeGreater : - public std::binary_function< const Breakpoint, const Breakpoint, bool > -{ -public: - //! Return true if its first Breakpoint argument has amplitude greater - //! than that of its second Breakpoint argument, and false otherwise. - bool operator()( const Breakpoint & lhs, const Breakpoint & rhs ) const - { return lhs.amplitude() > rhs.amplitude(); } -}; - -//! Old name for compareAmplitudeGreater. -//! \deprecated use compareAmplitudeGreater instead. -typedef compareAmplitudeGreater greater_amplitude; - -// --------------------------------------------------------------------------- -// compareAmplitudeLess -// -//! Comparitor (binary) functor returning true if its first Breakpoint -//! argument has amplitude less than that of its second Breakpoint argument, -//! and false otherwise. -// -class compareAmplitudeLess : - public std::binary_function< const Breakpoint, const Breakpoint, bool > -{ -public: - //! Return true if its first Breakpoint argument has amplitude greater - //! than that of its second Breakpoint argument, and false otherwise. - bool operator()( const Breakpoint & lhs, const Breakpoint & rhs ) const - { return lhs.amplitude() < rhs.amplitude(); } -}; - -} // end of namespace BreakpointUtils - -} // end of namespace Loris - -#endif /* ndef INCLUDE_BREAKPOINTUTILS_H */ diff --git a/loris_library/Source/src/Channelizer.cpp b/loris_library/Source/src/Channelizer.cpp deleted file mode 100644 index 5ab6484..0000000 --- a/loris_library/Source/src/Channelizer.cpp +++ /dev/null @@ -1,590 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Channelizer.C - * - * Implementation of class Channelizer. - * - * Kelly Fitz, 21 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Channelizer.h" -#include "Envelope.h" -#include "LinearEnvelope.h" -#include "Partial.h" -#include "PartialList.h" -#include "Notifier.h" - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// Channelizer constructor from reference envelope -// --------------------------------------------------------------------------- -//! Construct a new Channelizer using the specified reference -//! Envelope to represent the a numbered channel. If the sound -//! being channelized is known to have detuned harmonics, a -//! stretching factor can be specified (defaults to 0 for no -//! stretching). The stretching factor can be computed using -//! the static member computeStretchFactor. -//! -//! \param refChanFreq is an Envelope representing the center frequency -//! of a channel. -//! \param refChanLabel is the corresponding channel number (i.e. 1 -//! if refChanFreq is the lowest-frequency channel, and all -//! other channels are harmonics of refChanFreq, or 2 if -//! refChanFreq tracks the second harmonic, etc.). -//! \param stretchFactor is a stretching factor to account for detuned -//! harmonics, default is 0. -//! -//! \throw InvalidArgument if refChanLabel is not positive. -//! \throw InvalidArgument if stretchFactor is negative. -// -Channelizer::Channelizer( const Envelope & refChanFreq, int refChanLabel, double stretchFactor ) : - _refChannelFreq( refChanFreq.clone() ), - _refChannelLabel( refChanLabel ), - _stretchFactor( stretchFactor ), - _ampWeighting( 0 ) -{ - if ( refChanLabel <= 0 ) - { - Throw( InvalidArgument, "Channelizer reference label must be positive." ); - } - if ( stretchFactor < 0. ) - { - Throw( InvalidArgument, "Channelizer stretch factor must be non-negative." ); - } -} - -// --------------------------------------------------------------------------- -// Channelizer constructor from constant reference frequency -// --------------------------------------------------------------------------- -//! Construct a new Channelizer having a constant reference frequency. -//! The specified frequency is the center frequency of the lowest-frequency -//! channel (for a harmonic sound, the channel containing the fundamental -//! Partial. -//! -//! \param refFreq is the reference frequency (in Hz) corresponding -//! to the first frequency channel. -//! \param stretchFactor is a stretching factor to account for detuned -//! harmonics, default is 0. -//! -//! \throw InvalidArgument is the reference frequency is not positive -Channelizer::Channelizer( double refFreq, double stretchFactor ) : - _refChannelFreq( new LinearEnvelope( refFreq ) ), - _refChannelLabel( 1 ), - _stretchFactor( stretchFactor ), - _ampWeighting( 0 ) -{ - if ( refFreq <= 0 ) - { - Throw( InvalidArgument, "Channelizer reference frequency must be positive." ); - } - if ( stretchFactor < 0. ) - { - Throw( InvalidArgument, "Channelizer stretch factor must be non-negative." ); - } -} - - -// --------------------------------------------------------------------------- -// Channelizer copy constructor -// --------------------------------------------------------------------------- -//! Construct a new Channelizer that is an exact copy of another. -//! The copy represents the same set of frequency channels, constructed -//! from the same reference Envelope and channel number. -//! -//! \param other is the Channelizer to copy -// -Channelizer::Channelizer( const Channelizer & other ) : - _refChannelFreq( other._refChannelFreq->clone() ), - _refChannelLabel( other._refChannelLabel ), - _stretchFactor( other._stretchFactor ), - _ampWeighting( other._ampWeighting ) -{ -} - -// --------------------------------------------------------------------------- -// Channelizer assignment -// --------------------------------------------------------------------------- -//! Assignment operator: make this Channelizer an exact copy of another. -//! This Channelizer is made to represent the same set of frequency channels, -//! constructed from the same reference Envelope and channel number as @a rhs. -//! -//! \param rhs is the Channelizer to copy -// -Channelizer & -Channelizer::operator=( const Channelizer & rhs ) -{ - if ( &rhs != this ) - { - _refChannelFreq.reset( rhs._refChannelFreq->clone() ); - _refChannelLabel = rhs._refChannelLabel; - _stretchFactor = rhs._stretchFactor; - _ampWeighting = rhs._ampWeighting; - } - return *this; -} - - -// --------------------------------------------------------------------------- -// Channelizer destructor -// --------------------------------------------------------------------------- -//! Destroy this Channelizer. -// -Channelizer::~Channelizer( void ) -{ -} - -// --------------------------------------------------------------------------- -// amplitudeWeighting -// --------------------------------------------------------------------------- -//! Return the exponent applied to amplitude before weighting -//! the instantaneous estimate of the frequency channel number -//! for a Partial. zero (default) for no weighting, 1 for linear -//! amplitude weighting, 2 for power weighting, etc. -//! Amplitude weighting is a bad idea for many sounds, particularly -//! those with transients, for which it may emphasize the part of -//! the Partial having the least reliable frequency estimate. -// -double Channelizer::amplitudeWeighting( void ) const -{ - return _ampWeighting; -} - -// --------------------------------------------------------------------------- -// setAmplitudeWeighting -// --------------------------------------------------------------------------- -//! Set the exponent applied to amplitude before weighting -//! the instantaneous estimate of the frequency channel number -//! for a Partial. zero (default) for no weighting, 1 for linear -//! amplitude weighting, 2 for power weighting, etc. -//! Amplitude weighting is a bad idea for many sounds, particularly -//! those with transients, for which it may emphasize the part of -//! the Partial having the least reliable frequency estimate. -// -void Channelizer::setAmplitudeWeighting( double x ) -{ - _ampWeighting = x; -} - -// --------------------------------------------------------------------------- -// stretchFactor -// --------------------------------------------------------------------------- -//! Return the stretching factor used to account for detuned -//! harmonics, as in a piano tone. Normally set to 0 for -//! in-tune harmonics. -//! -//! The stretching factor is a small positive number for -//! heavy vibrating strings (as in pianos) for which the -//! mass of the string significantly affects the frequency -//! of the vibrating modes. See Martin Keane, "Understanding -//! the complex nature of the piano tone", 2004, for a discussion -//! and the source of the mode frequency stretching algorithms -//! implemented here. -// -double Channelizer::stretchFactor( void ) const -{ - return _stretchFactor; -} - -// --------------------------------------------------------------------------- -// setStretchFactor -// --------------------------------------------------------------------------- -//! Set the stretching factor used to account for detuned -//! harmonics, as in a piano tone. Normally set to 0 for -//! in-tune harmonics. The stretching factor for massy -//! vibrating strings (like pianos) can be computed from -//! the physical characteristics of the string, or using -//! computeStretchFactor(). -//! -//! The stretching factor is a small positive number for -//! heavy vibrating strings (as in pianos) for which the -//! mass of the string significantly affects the frequency -//! of the vibrating modes. See Martin Keane, "Understanding -//! the complex nature of the piano tone", 2004, for a discussion -//! and the source of the mode frequency stretching algorithms -//! implemented here. -//! -//! \throw InvalidArgument if stretch is negative. -// -void Channelizer::setStretchFactor( double stretch ) -{ - if ( stretch < 0. ) - { - Throw( InvalidArgument, "Channelizer stretch factor must be non-negative." ); - } - _stretchFactor = stretch; -} - -// --------------------------------------------------------------------------- -// setStretchFactor -// --------------------------------------------------------------------------- -//! Set the stretching factor used to account for (consistently) -//! detuned harmonics, as in a piano tone, from a pair of -//! mode (harmonic) frequencies and numbers. -//! -//! The stretching factor is a small positive number for -//! heavy vibrating strings (as in pianos) for which the -//! mass of the string significantly affects the frequency -//! of the vibrating modes. See Martin Keane, "Understanding -//! the complex nature of the piano tone", 2004, for a discussion -//! and the source of the mode frequency stretching algorithms -//! implemented here. -//! -//! The stretching factor is computed using computeStretchFactor, -//! but only a valid stretch factor will ever be assigned. If an -//! invalid (negative) stretching factor is computed for the -//! specified frequencies and mode numbers, the stretch factor -//! will be set to zero. -//! -//! \param fm is the frequency of the Mth stretched harmonic -//! \param m is the harmonic number of the harmonic whose frequnecy is fm -//! \param fn is the frequency of the Nth stretched harmonic -//! \param n is the harmonic number of the harmonic whose frequnecy is fn -void Channelizer::setStretchFactor( double fm, int m, double fn, int n ) -{ - const double B = computeStretchFactor( fm, m, fn, n ); - if ( 0 < B ) - { - _stretchFactor = B; - } - else - { - _stretchFactor = 0; - } -} - -// --------------------------------------------------------------------------- -// computeStretchFactor (STATIC class member) -// --------------------------------------------------------------------------- -//! Static member to compute the stretch factor for a sound having -//! (consistently) detuned harmonics, like piano tones. -//! -//! The stretching factor is a small positive number for -//! heavy vibrating strings (as in pianos) for which the -//! mass of the string significantly affects the frequency -//! of the vibrating modes. See Martin Keane, "Understanding -//! the complex nature of the piano tone", 2004, for a discussion -//! and the source of the mode frequency stretching algorithms -//! implemented here. -//! -//! The value returned by this function MAY NOT be a valid stretch -//! factor. If this function returns a negative stretch factor, -//! then the specified pair of frequencies and mode numbers cannot -//! be used to estimate the effects of string mass on mode frequency -//! (because the negative stretch factor implies a physical -//! impossibility, like negative mass or negative length). -//! -//! \param fm is the frequency of the Mth stretched harmonic -//! \param m is the harmonic number of the harmonic whose frequnecy is fm -//! \param fn is the frequency of the Nth stretched harmonic -//! \param n is the harmonic number of the harmonic whose frequnecy is fn -//! \returns the stretching factor, usually a very small positive -//! floating point number, or 0 for pefectly tuned harmonics -//! (that is, if fn = n*f1). -// -double -Channelizer::computeStretchFactor( double fm, int m, double fn, int n ) -{ - if ( fm <= 0. || fn <= 0. ) - { - Throw( InvalidArgument, "Channelizer stretched harmonic frequencies must be positive." ); - } - if ( m <= 0 || n <= 0 ) - { - Throw( InvalidArgument, "Channelizer stretched harmonic numbers must be positive." ); - } - - // K is a factor that depends on the frequencies - // of the two stretched harmonics, equal to 1.0 for - // perfectly tuned (not stretched) harmonics - const double K = (m*fn) / (n*fm); - - const double num = 1. - (K*K); - const double denom = (K*K*m*m) - (n*n); -/* - OLD and wrong I think - double num = (fn*fn) - (n*n*fref*fref); - double denom = (n*n*n*n)*(fref*fref); -*/ - - return num / denom; -} - -// --------------------------------------------------------------------------- -// computeStretchFactor (STATIC class member) -// --------------------------------------------------------------------------- -//! Static member to compute the stretch factor for a sound having -//! (consistently) detuned harmonics, like piano tones. Legacy version -//! that assumes the first argument corresponds to the first partial. -//! -//! \param f1 is the frequency of the lowest numbered (1) partial. -//! \param fn is the frequency of the Nth stretched harmonic -//! \param n is the harmonic number of the harmonic whose frequnecy is fn -//! \returns the stretching factor, usually a very small positive -//! floating point number, or 0 for pefectly tuned harmonics -//! (that is, for harmonic frequencies fn = n*f1). -// -double -Channelizer::computeStretchFactor( double f1, double fn, double n ) -{ - return computeStretchFactor( f1, 1, fn, int(n + 0.5) ); -} - -// --------------------------------------------------------------------------- -// referenceFrequencyAt -// --------------------------------------------------------------------------- -//! Compute the reference frequency at the specified time. For non-stretched -//! harmonics, this is simply the ratio of the reference envelope evaluated -//! at that time to the reference channel number, and is the center frequecy -//! for the lowest channel. For stretched harmonics, the reference frequency -//! is NOT equal to the center frequency of any of the channels, and is also -//! a function of the stretch factor. -// -double Channelizer::referenceFrequencyAt( double time ) const -{ - const double N = _refChannelLabel; - double fref = _refChannelFreq->valueAt( time ) / N; - - if ( 0 != _stretchFactor ) - { - double divisor = std::sqrt( 1.0 + ( _stretchFactor*N*N) ); - fref = fref / divisor; - } - - return fref; -} - -// --------------------------------------------------------------------------- -// computeFractionalChannelNumber -// --------------------------------------------------------------------------- -//! Compute the (fractional) channel number estimate for a Partial having a -//! given frequency at a specified time. For ordinary harmonics, this -//! is simply the ratio of the specified frequency to the reference -//! frequency at the specified time. For stretched harmonics (as in -//! a piano), the stretching factor is used to compute the frequency -//! of the corresponding modes of a massy string. See Martin Keane, -//! "Understanding the complex nature of the piano tone", 2004, for -//! the source of the mode frequency stretching algorithms -//! implemented here. -//! -//! The fractional channel number is used internally to determine -//! a best estimate for the channel number (label) for a Partial -//! having time-varying frequency. -//! -//! \param time is the time (in seconds) at which to evalute -//! the reference envelope -//! \param frequency is the frequency (in Hz) for wihch the channel -//! number is to be determined -//! \return the fractional channel number corresponding to the specified -//! frequency and time -// -double -Channelizer::computeFractionalChannelNumber( double time, double frequency ) const -{ - double refFreq = referenceFrequencyAt( time ); - - if ( 0 == _stretchFactor ) - { - return frequency / refFreq; - } - - /* - const double frefsqrd = fref*fref; - double num = sqrt( (frefsqrd*frefsqrd) + (4*stretch*frefsqrd*fn*fn) ) - (frefsqrd); - double denom = 2*stretch*frefsqrd; - return sqrt( num / denom ); - */ - - // else: - // avoid squaring big numbers... two sqrts kind of sucks too. - const double rB = 1. / _stretchFactor; // reciprocal of B, the stretch factor - const double fratio = frequency / refFreq; - return std::sqrt( std::sqrt( (.25 * rB * rB) + (fratio * fratio * rB) ) - (.5 * rB) ); -} - -// --------------------------------------------------------------------------- -// computeChannelNumber -// --------------------------------------------------------------------------- -//! Compute the (fractional) channel number estimate for a Partial having a -//! given frequency at a specified time. For ordinary harmonics, this -//! is simply the ratio of the specified frequency to the reference -//! frequency at the specified time. For stretched harmonics (as in -//! a piano), the stretching factor is used to compute the frequency -//! of the corresponding modes of a massy string. See Martin Keane, -//! "Understanding the complex nature of the piano tone", 2004, for -//! the source of the mode frequency stretching algorithms -//! implemented here. -//! -//! \param time is the time (in seconds) at which to evalute -//! the reference envelope -//! \param frequency is the frequency (in Hz) for wihch the channel -//! number is to be determined -//! \return the channel number corresponding to the specified -//! frequency and time -// -int -Channelizer::computeChannelNumber( double time, double frequency ) const -{ - return int( computeFractionalChannelNumber( time, frequency ) + 0.5 ); -} - -// --------------------------------------------------------------------------- -// channelFrequencyAt -// --------------------------------------------------------------------------- -//! Compute the center frequency of one a channel at the specified -//! time. For non-stretched harmonics, this is simply the value -//! of the reference envelope scaled by the ratio of the specified -//! channel number to the reference channel number. For stretched -//! harmonics, the channel center frequency is computed using the -//! stretch factor. See Martin Keane, "Understanding -//! the complex nature of the piano tone", 2004, for a discussion -//! and the source of the mode frequency stretching algorithms -//! implemented here. -//! -//! \param time is the time (in seconds) at which to evalute -//! the reference envelope -//! \param channel is the frequency channel (or harmonic, or vibrational -//! mode) number whose frequency is to be determined -//! \return the center frequency in Hz of the specified frequency channel -//! at the specified time -// -double -Channelizer::channelFrequencyAt( double time, int channel ) const -{ - const double fref = referenceFrequencyAt( time ); - double fn = channel * fref; - - if ( 0 != _stretchFactor ) - { - const double scale = std::sqrt( 1.0 + (_stretchFactor*channel*channel) ); - fn = fn * scale; - } - return fn; -} - -// --------------------------------------------------------------------------- -// channelize (one Partial) -// --------------------------------------------------------------------------- -//! Label a Partial with the number of the frequency channel corresponding to -//! the average frequency over all the Partial's Breakpoints. -//! -//! \param partial is the Partial to label. -// -void -Channelizer::channelize( Partial & partial ) const -{ - using std::pow; - - debugger << "channelizing Partial with " << partial.numBreakpoints() << " Breakpoints" << endl; - - // compute an amplitude-weighted average channel - // label for each Partial: - //double ampsum = 0.; - double weightedlabel = 0.; - Partial::const_iterator bp; - for ( bp = partial.begin(); bp != partial.end(); ++bp ) - { - - double f = bp.breakpoint().frequency(); - double t = bp.time(); - - double weight = 1; - if ( 0 != _ampWeighting ) - { - // This used to be an amplitude-weighted avg, but for many sounds, - // particularly those for which the weighted avg would be very - // different from the simple avg, the amplitude-weighted avg - // emphasized the part of the sound in which the frequency estimates - // are least reliable (e.g. a piano tone). The unweighted - // average should give more intuitive results in most cases. - - // use sinusoidal amplitude: - double a = bp.breakpoint().amplitude() * std::sqrt( 1. - bp.breakpoint().bandwidth() ); - weight = pow( a, _ampWeighting ); - } - - weightedlabel += weight * computeFractionalChannelNumber( t, f ); - } - - int label = 0; - if ( 0 < partial.numBreakpoints() ) // should always be the case - { - label = (int)((weightedlabel / partial.numBreakpoints()) + 0.5); - } - Assert( label >= 0 ); - - // assign label, and remember it, but - // only if it is a valid (positive) - // distillation label: - partial.setLabel( label ); - -} - -// -- simplified interface -- - - -// --------------------------------------------------------------------------- -// channelize (static simplified interface) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a PartialList (simplified interface). -//! -//! Construct a Channelizer using the specified Envelope -//! and reference label, and use it to channelize a -//! sequence of Partials. -//! -//! \param partials is the sequence of Partials to -//! channelize. -//! \param refChanFreq is an Envelope representing the center frequency -//! of a channel. -//! \param refChanLabel is the corresponding channel number (i.e. 1 -//! if refChanFreq is the lowest-frequency channel, and all -//! other channels are harmonics of refChanFreq, or 2 if -//! refChanFreq tracks the second harmonic, etc.). -//! \throw InvalidArgument if refChanLabel is not positive. -// -void -Channelizer::channelize( PartialList & partials, - const Envelope & refChanFreq, int refChanLabel ) -{ - Channelizer instance( refChanFreq, refChanLabel ); - - for ( PartialList::iterator it = partials.begin(); it != partials.end(); ++it ) - { - instance.channelize( *it ); - } -} - - -} // end of namespace Loris diff --git a/loris_library/Source/src/Channelizer.h b/loris_library/Source/src/Channelizer.h deleted file mode 100644 index d57932b..0000000 --- a/loris_library/Source/src/Channelizer.h +++ /dev/null @@ -1,526 +0,0 @@ -#ifndef INCLUDE_CHANNELIZER_H -#define INCLUDE_CHANNELIZER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Channelizer.h - * - * Definition of class Loris::Channelizer. - * - * Kelly Fitz, 21 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "PartialList.h" - -#include - -// begin namespace -namespace Loris { - -class Envelope; -class Partial; - -// --------------------------------------------------------------------------- -// Channelizer -// -//! Class Channelizer represents an algorithm for automatic labeling of -//! a sequence of Partials. Partials must be labeled in -//! preparation for morphing (see Morpher) to establish correspondences -//! between Partials in the morph source and target sounds. -//! -//! Channelized partials are labeled according to their adherence to a -//! harmonic frequency structure with a time-varying fundamental -//! frequency. The frequency spectrum is partitioned into -//! non-overlapping channels having time-varying center frequencies that -//! are harmonic (integer) multiples of a specified reference frequency -//! envelope, and each channel is identified by a unique label equal to -//! its harmonic number. Each Partial is assigned the label -//! corresponding to the channel containing the greatest portion of its -//! (the Partial's) energy. -//! -//! A reference frequency Envelope for channelization and the channel -//! number to which it corresponds (1 for an Envelope that tracks the -//! Partial at the fundamental frequency) must be specified. The -//! reference Envelope can be constructed explcitly, point by point -//! (using, for example, the BreakpointEnvelope class), or constructed -//! automatically using the FrequencyReference class. -//! -//! The Channelizer can be configured with a stretch factor, to accomodate -//! detuned harmonics, as in the case of piano tones. The static member -//! computeStretchFactor can compute the apppropriate stretch factor, given -//! a pair of partials. This computation is based on formulae given in -//! "Understanding the complex nature of the piano tone" by Martin Keane -//! at the Acoustics Research Centre at the University of Aukland (Feb 2004). -//! The stretching factor must be non-negative (and is zero for perfectly -//! tunes harmonics). Even in the case of stretched harmonics, the -//! reference frequency envelope is assumed to track the frequency of -//! one of the partials, and the center frequency of the corresponding -//! channel, even though it may represent a stretched harmonic. -//! -//! Channelizer is a leaf class, do not subclass. -// -class Channelizer -{ -// -- implementaion -- - std::auto_ptr< Envelope > _refChannelFreq; //! the reference frequency envelope - - int _refChannelLabel; //! the channel number corresponding to the - //! reference frequency (1 for the fundamental) - - double _stretchFactor; //! stretching factor to account for - //! detuned harmonics, as in the case of the piano; - //! can be computed using the static member - //! computeStretchFactor. Should be 0 for most - //! (strongly harmonic) sounds. - - double _ampWeighting; //! exponent for amplitude weighting in channel - //! computation, 0 for no weighting, 1 for linear - //! amplitude weighting, 2 for power weighting, etc. - //! default is 0, amplitude weighting is a bad idea - //! for many sounds - -// -- public interface -- -public: -// -- construction -- - - //! Construct a new Channelizer using the specified reference - //! Envelope to represent the a numbered channel. If the sound - //! being channelized is known to have detuned harmonics, a - //! stretching factor can be specified (defaults to 0 for no - //! stretching). The stretching factor can be computed using - //! the static member computeStretchFactor. - //! - //! \param refChanFreq is an Envelope representing the center frequency - //! of a channel. - //! \param refChanLabel is the corresponding channel number (i.e. 1 - //! if refChanFreq is the lowest-frequency channel, and all - //! other channels are harmonics of refChanFreq, or 2 if - //! refChanFreq tracks the second harmonic, etc.). - //! \param stretchFactor is a stretching factor to account for detuned - //! harmonics, default is 0. - //! - //! \throw InvalidArgument if refChanLabel is not positive. - //! \throw InvalidArgument if stretchFactor is negative. - Channelizer( const Envelope & refChanFreq, int refChanLabel, double stretchFactor = 0 ); - - //! Construct a new Channelizer having a constant reference frequency. - //! The specified frequency is the center frequency of the lowest-frequency - //! channel (for a harmonic sound, the channel containing the fundamental - //! Partial. - //! - //! \param refFreq is the reference frequency (in Hz) corresponding - //! to the first frequency channel. - //! \param stretchFactor is a stretching factor to account for detuned - //! harmonics, default is 0. - //! - //! \throw InvalidArgument if refChanLabel is not positive. - //! \throw InvalidArgument if stretchFactor is negative. - Channelizer( double refFreq, double stretchFactor = 0 ); - - //! Construct a new Channelizer that is an exact copy of another. - //! The copy represents the same set of frequency channels, constructed - //! from the same reference Envelope and channel number. - //! - //! \param other is the Channelizer to copy - Channelizer( const Channelizer & other ); - - //! Assignment operator: make this Channelizer an exact copy of another. - //! This Channelizer is made to represent the same set of frequency channels, - //! constructed from the same reference Envelope and channel number as rhs. - //! - //! \param rhs is the Channelizer to copy - Channelizer & operator=( const Channelizer & rhs ); - - //! Destroy this Channelizer. - ~Channelizer( void ); - -// -- channelizing -- - - //! Label a Partial with the number of the frequency channel containing - //! the greatest portion of its (the Partial's) energy. - //! - //! \param partial is the Partial to label. - void channelize( Partial & partial ) const; - - //! Assign each Partial in the specified half-open (STL-style) range - //! the label corresponding to the frequency channel containing the - //! greatest portion of its (the Partial's) energy. - //! - //! \param begin is the beginning of the range of Partials to channelize - //! \param end is (one-past) the end of the range of Partials to channelize - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void channelize( Iter begin, Iter end ) const; -#else - void channelize( PartialList::iterator begin, PartialList::iterator end ) const; -#endif - - //! Function call operator: same as channelize(). -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void operator() ( Iter begin, Iter end ) const -#else - inline - void operator() ( PartialList::iterator begin, PartialList::iterator end ) const -#endif - { channelize( begin, end ); } - - //! Compute the center frequency of one a channel at the specified - //! time. For non-stretched harmonics, this is simply the value - //! of the reference envelope scaled by the ratio of the specified - //! channel number to the reference channel number. For stretched - //! harmonics, the channel center frequency is computed using the - //! stretch factor. See Martin Keane, "Understanding - //! the complex nature of the piano tone", 2004, for a discussion - //! and the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! \param time is the time (in seconds) at which to evalute - //! the reference envelope - //! \param channel is the frequency channel (or harmonic, or vibrational - //! mode) number whose frequency is to be determined - //! \return the center frequency in Hz of the specified frequency channel - //! at the specified time - double channelFrequencyAt( double time, int channel ) const; - - //! Compute the (fractional) channel number estimate for a Partial having a - //! given frequency at a specified time. For ordinary harmonics, this - //! is simply the ratio of the specified frequency to the reference - //! frequency at the specified time. For stretched harmonics (as in - //! a piano), the stretching factor is used to compute the frequency - //! of the corresponding modes of a massy string. See Martin Keane, - //! "Understanding the complex nature of the piano tone", 2004, for - //! the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! \param time is the time (in seconds) at which to evalute - //! the reference envelope - //! \param frequency is the frequency (in Hz) for wihch the channel - //! number is to be determined - //! \return the channel number corresponding to the specified - //! frequency and time - int computeChannelNumber( double time, double frequency ) const; - - //! Compute the (fractional) channel number estimate for a Partial having a - //! given frequency at a specified time. For ordinary harmonics, this - //! is simply the ratio of the specified frequency to the reference - //! frequency at the specified time. For stretched harmonics (as in - //! a piano), the stretching factor is used to compute the frequency - //! of the corresponding modes of a massy string. See Martin Keane, - //! "Understanding the complex nature of the piano tone", 2004, for - //! the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! The fractional channel number is used internally to determine - //! a best estimate for the channel number (label) for a Partial - //! having time-varying frequency. - //! - //! \param time is the time (in seconds) at which to evalute - //! the reference envelope - //! \param frequency is the frequency (in Hz) for wihch the channel - //! number is to be determined - //! \return the fractional channel number corresponding to the specified - //! frequency and time - double computeFractionalChannelNumber( double time, double frequency ) const; - - - //! Compute the reference frequency at the specified time. For non-stretched - //! harmonics, this is simply the ratio of the reference envelope evaluated - //! at that time to the reference channel number, and is the center frequecy - //! for the lowest channel. For stretched harmonics, the reference frequency - //! is NOT equal to the center frequency of any of the channels, and is also - //! a function of the stretch factor. - //! - //! \param time is the time (in seconds) at which to evalute - //! the reference envelope - double referenceFrequencyAt( double time ) const; - -// -- access/mutation -- - - //! Return the exponent applied to amplitude before weighting - //! the instantaneous estimate of the frequency channel number - //! for a Partial. zero (default) for no weighting, 1 for linear - //! amplitude weighting, 2 for power weighting, etc. - //! Amplitude weighting is a bad idea for many sounds, particularly - //! those with transients, for which it may emphasize the part of - //! the Partial having the least reliable frequency estimate. - double amplitudeWeighting( void ) const; - - //! Set the exponent applied to amplitude before weighting - //! the instantaneous estimate of the frequency channel number - //! for a Partial. zero (default) for no weighting, 1 for linear - //! amplitude weighting, 2 for power weighting, etc. - //! Amplitude weighting is a bad idea for many sounds, particularly - //! those with transients, for which it may emphasize the part of - //! the Partial having the least reliable frequency estimate. - void setAmplitudeWeighting( double expon ); - - //! Return the stretching factor used to account for detuned - //! harmonics, as in a piano tone. Normally set to 0 for - //! in-tune harmonics. - //! - //! The stretching factor is a small positive number for - //! heavy vibrating strings (as in pianos) for which the - //! mass of the string significantly affects the frequency - //! of the vibrating modes. See Martin Keane, "Understanding - //! the complex nature of the piano tone", 2004, for a discussion - //! and the source of the mode frequency stretching algorithms - //! implemented here. - double stretchFactor( void ) const; - - //! Set the stretching factor used to account for detuned - //! harmonics, as in a piano tone. Normally set to 0 for - //! in-tune harmonics. The stretching factor for massy - //! vibrating strings (like pianos) can be computed from - //! the physical characteristics of the string, or using - //! computeStretchFactor(). - //! - //! The stretching factor is a small positive number for - //! heavy vibrating strings (as in pianos) for which the - //! mass of the string significantly affects the frequency - //! of the vibrating modes. See Martin Keane, "Understanding - //! the complex nature of the piano tone", 2004, for a discussion - //! and the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! \throw InvalidArgument if stretch is negative. - void setStretchFactor( double stretch ); - - -// -- static members -- - - - //! Static member to compute the stretch factor for a sound having - //! (consistently) detuned harmonics, like piano tones. - //! - //! The stretching factor is a small positive number for - //! heavy vibrating strings (as in pianos) for which the - //! mass of the string significantly affects the frequency - //! of the vibrating modes. See Martin Keane, "Understanding - //! the complex nature of the piano tone", 2004, for a discussion - //! and the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! The value returned by this function MAY NOT be a valid stretch - //! factor. If this function returns a negative stretch factor, - //! then the specified pair of frequencies and mode numbers cannot - //! be used to estimate the effects of string mass on mode frequency - //! (because the negative stretch factor implies a physical - //! impossibility, like negative mass or negative length). - //! - //! \param fm is the frequency of the Mth stretched harmonic - //! \param m is the harmonic number of the harmonic whose frequnecy is fm - //! \param fn is the frequency of the Nth stretched harmonic - //! \param n is the harmonic number of the harmonic whose frequnecy is fn - //! \returns the stretching factor, usually a very small positive - //! floating point number, or 0 for pefectly tuned harmonics - //! (that is, if fn = n*f1). - static double computeStretchFactor( double fm, int m, double fn, int n ); - - -// -- simplified interface -- - - //! Static member that constructs an instance and applies - //! it to a PartialList (simplified interface). - //! - //! Construct a Channelizer using the specified Envelope - //! and reference label, and use it to channelize a - //! sequence of Partials. - //! - //! \param partials is the sequence of Partials to - //! channelize. - //! \param refChanFreq is an Envelope representing the center frequency - //! of a channel. - //! \param refChanLabel is the corresponding channel number (i.e. 1 - //! if refChanFreq is the lowest-frequency channel, and all - //! other channels are harmonics of refChanFreq, or 2 if - //! refChanFreq tracks the second harmonic, etc.). - //! \throw InvalidArgument if refChanLabel is not positive. - static - void channelize( PartialList & partials, - const Envelope & refChanFreq, int refChanLabel ); - - - -// -- DEPRECATED members -- - - //! DEPRECATED - //! - //! Set the stretching factor used to account for (consistently) - //! detuned harmonics, as in a piano tone, from a pair of - //! mode (harmonic) frequencies and numbers. - //! - //! The stretching factor is a small positive number for - //! heavy vibrating strings (as in pianos) for which the - //! mass of the string significantly affects the frequency - //! of the vibrating modes. See Martin Keane, "Understanding - //! the complex nature of the piano tone", 2004, for a discussion - //! and the source of the mode frequency stretching algorithms - //! implemented here. - //! - //! The stretching factor is computed using computeStretchFactor, - //! but only a valid stretch factor will ever be assigned. If an - //! invalid (negative) stretching factor is computed for the - //! specified frequencies and mode numbers, the stretch factor - //! will be set to zero. - //! - //! \param fm is the frequency of the Mth stretched harmonic - //! \param m is the harmonic number of the harmonic whose frequnecy is fm - //! \param fn is the frequency of the Nth stretched harmonic - //! \param n is the harmonic number of the harmonic whose frequnecy is fn - void setStretchFactor( double fm, int m, double fn, int n ); - - - //! DEPRECATED - //! - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Channelizer using the specified Envelope - //! and reference label, and use it to channelize a - //! sequence of Partials. - //! - //! \param begin is the beginning of a sequence of Partials to - //! channelize. - //! \param end is the end of a sequence of Partials to - //! channelize. - //! \param refChanFreq is an Envelope representing the center frequency - //! of a channel. - //! \param refChanLabel is the corresponding channel number (i.e. 1 - //! if refChanFreq is the lowest-frequency channel, and all - //! other channels are harmonics of refChanFreq, or 2 if - //! refChanFreq tracks the second harmonic, etc.). - //! \throw InvalidArgument if refChanLabel is not positive. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - static - void channelize( Iter begin, Iter end, - const Envelope & refChanFreq, int refChanLabel ); -#else - static inline - void channelize( PartialList::iterator begin, PartialList::iterator end, - const Envelope & refChanFreq, int refChanLabel ); -#endif - - - //! DEPRECATED - //! - //! Static member to compute the stretch factor for a sound having - //! (consistently) detuned harmonics, like piano tones. Legacy version - //! that assumes the first argument corresponds to the first partial. - //! - //! \param f1 is the frequency of the lowest numbered (1) partial. - //! \param fn is the frequency of the Nth stretched harmonic - //! \param n is the harmonic number of the harmonic whose frequnecy is fn - //! \returns the stretching factor, usually a very small positive - //! floating point number, or 0 for pefectly tuned harmonics - //! (that is, for harmonic frequencies fn = n*f1). - static double computeStretchFactor( double f1, double fn, double n ); - -}; // end of class Channelizer - -// --------------------------------------------------------------------------- -// channelize (sequence of Partials) -// --------------------------------------------------------------------------- -//! Assign each Partial in the specified half-open (STL-style) range -//! the label corresponding to the frequency channel containing the -//! greatest portion of its (the Partial's) energy. -//! -//! \param begin is the beginning of the range of Partials to channelize -//! \param end is (one-past) the end of the range of Partials o channelize -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Channelizer::channelize( Iter begin, Iter end ) const -#else -inline -void Channelizer::channelize( PartialList::iterator begin, PartialList::iterator end ) const -#endif -{ - while ( begin != end ) - { - channelize( *begin++ ); - } -} - -// --------------------------------------------------------------------------- -// channelize (static) -// --------------------------------------------------------------------------- -//! DEPRECATED -//! -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! Construct a Channelizer using the specified Envelope -//! and reference label, and use it to channelize a -//! sequence of Partials. -//! -//! \param begin is the beginning of a sequence of Partials to -//! channelize. -//! \param end is the end of a sequence of Partials to -//! channelize. -//! \param refChanFreq is an Envelope representing the center frequency -//! of a channel. -//! \param refChanLabel is the corresponding channel number (i.e. 1 -//! if refChanFreq is the lowest-frequency channel, and all -//! other channels are harmonics of refChanFreq, or 2 if -//! refChanFreq tracks the second harmonic, etc.). -//! \throw InvalidArgument if refChanLabel is not positive. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Channelizer::channelize( Iter begin, Iter end, - const Envelope & refChanFreq, int refChanLabel ) -#else -inline -void Channelizer::channelize( PartialList::iterator begin, PartialList::iterator end, - const Envelope & refChanFreq, int refChanLabel ) -#endif -{ - Channelizer instance( refChanFreq, refChanLabel ); - while ( begin != end ) - { - instance.channelize( *begin++ ); - } -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_CHANNELIZER_H */ diff --git a/loris_library/Source/src/Collator.cpp b/loris_library/Source/src/Collator.cpp deleted file mode 100644 index 1cbddbf..0000000 --- a/loris_library/Source/src/Collator.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Collator.h - * - * Definition of class Collator. - * - * Kelly Fitz, 29 April 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Collator.h" -#include "Breakpoint.h" -#include "BreakpointUtils.h" -#include "LorisExceptions.h" -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" -#include "Notifier.h" - -#include -#include -#include - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// Collator constructor -// --------------------------------------------------------------------------- -//! Construct a new Collator using the specified fade and gap times -//! between Partials. When two Partials are joined, the collated Partial -//! fades out at the end of the earlier Partial and back in again -//! at the onset of the later one. The fade time is the time over -//! which these fades occur. By default, use a 5 ms fade time. -//! The gap time is the additional time over which a Partial faded -//! out must remain at zero amplitude before it can fade back in. -//! By default, use a gap time of one millisecond, to -//! prevent a pair of arbitrarily close null Breakpoints being -//! inserted. (Defaults are copied from the Distiller.) -//! -//! \param partialFadeTime is the time (in seconds) over -//! which Partials joined by distillation fade to -//! and from zero amplitude. Default is 0.005 (one -//! millisecond). -//! \param partialSilentTime is the minimum duration (in seconds) -//! of the silent (zero-amplitude) gap between two -//! Partials joined by distillation. (Default is -//! 0.001 (one millisecond). -Collator::Collator( double partialFadeTime, double partialSilentTime ) : - _fadeTime( partialFadeTime ), - _gapTime( partialSilentTime ) -{ - if ( _fadeTime <= 0.0 ) - { - Throw( InvalidArgument, "Collator fade time must be positive." ); - } - if ( _gapTime <= 0.0 ) - { - Throw( InvalidArgument, "Collator gap time must be positive." ); - } -} - -// -- helpers -- - -// --------------------------------------------------------------------------- -// helper predicates -// --------------------------------------------------------------------------- -static bool ends_earlier( const Partial & lhs, const Partial & rhs ) -{ - return lhs.endTime() < rhs.endTime(); -} - -struct ends_before : public std::unary_function< const Partial, bool > -{ - double t; - ends_before( double time ) : t( time ) {} - - bool operator() ( const Partial & p ) const - { return p.endTime() < t; } -}; - -// --------------------------------------------------------------------------- -// collateAux -// --------------------------------------------------------------------------- -//! Collate unlabeled (zero labeled) Partials into the smallest -//! possible number of Partials that does not combine any temporally -//! overlapping Partials. The unlabeled Partials are -//! collated in-place. -// -void Collator::collateAux( PartialList & unlabeled ) -{ - debugger << "Collator found " << unlabeled.size() - << " unlabeled Partials, collating..." << endl; - - // sort Partials by end time: - // thanks to Ulrike Axen for this optimal algorithm! - unlabeled.sort( ends_earlier ); - - // invariant: - // Partials in the range [partials.begin(), endcollated) - // are the collated Partials. - PartialList::iterator endcollated = unlabeled.begin(); - while ( endcollated != unlabeled.end() ) - { - // find a collated Partial that ends - // before this one begins. - // There must be a gap of at least - // twice the _fadeTime, because this algorithm - // does not remove any null Breakpoints, and - // because Partials joined in this way might - // be far apart in frequency. - const double clearance = (2.*_fadeTime) + _gapTime; - PartialList::iterator it = - std::find_if( unlabeled.begin(), endcollated, - ends_before( endcollated->startTime() - clearance) ); - - // if no such Partial exists, then this Partial - // becomes one of the collated ones, otherwise, - // insert two null Breakpoints, and then all - // the Breakpoints in this Partial: - if ( it != endcollated ) - { - Partial & addme = *endcollated; - Partial & collated = *it; - Assert( &addme != &collated ); - - // insert a null at the (current) end - // of collated: - double nulltime1 = collated.endTime() + _fadeTime; - Breakpoint null1( collated.frequencyAt(nulltime1), 0., - collated.bandwidthAt(nulltime1), collated.phaseAt(nulltime1) ); - collated.insert( nulltime1, null1 ); - - // insert a null at the beginning of - // of the current Partial: - double nulltime2 = addme.startTime() - _fadeTime; - Assert( nulltime2 >= nulltime1 ); - Breakpoint null2( addme.frequencyAt(nulltime2), 0., - addme.bandwidthAt(nulltime2), addme.phaseAt(nulltime2) ); - collated.insert( nulltime2, null2 ); - - // insert all the Breakpoints in addme - // into collated: - Partial::iterator addme_it; - for ( addme_it = addme.begin(); addme_it != addme.end(); ++addme_it ) - { - collated.insert( addme_it.time(), addme_it.breakpoint() ); - } - - // remove this Partial from the list: - endcollated = unlabeled.erase( endcollated ); - } - else - { - ++endcollated; - } - } - - debugger << "...now have " << unlabeled.size() << endl; -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Collator.h b/loris_library/Source/src/Collator.h deleted file mode 100644 index e1d441c..0000000 --- a/loris_library/Source/src/Collator.h +++ /dev/null @@ -1,366 +0,0 @@ -#ifndef INCLUDE_COLLATOR_H -#define INCLUDE_COLLATOR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Collator.h - * - * Definition of class Collator. - * - * Kelly Fitz, 29 April 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Distiller.h" // for default fade time and silent time -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Collator -// -//! Class Collator represents an algorithm for reducing a collection -//! of Partials into the smallest collection of "equivalent" Partials -//! by joining non-overlapping Partials end to end. -//! -//! Partials that are not labeled, that is, Partials having label 0, -//! are "collated " into groups of non-overlapping (in time) -//! Partials, and fused into a single Partial per group. -//! "Collating" is a bit like "distilling" but non-overlapping -//! Partials are grouped without regard to frequency proximity. This -//! algorithm produces the smallest-possible number of collated Partials. -//! Thanks to Ulrike Axen for providing this optimal algorithm. -//! -//! Collating modifies the Partial container (a PartialList). Only -//! unlabeled (labeled 0) Partials are affected by the collating -//! operation. Collated Partials are moved to the end of the -//! collection of Partials. -// -class Collator -{ -// -- instance variables -- - - double _fadeTime, _gapTime; - -// -- public interface -- -public: - -// -- global defaults and constants -- - - enum - { - - //! Default time in milliseconds over which Partials joined by - //! distillation fade to and from zero amplitude. Divide by - //! 1000 to use as a member function parameter. This parameter - //! should be the same in Distiller, Sieve, and Collator. - DefaultFadeTimeMs = Distiller::DefaultFadeTimeMs, - - //! Default minimum duration in milliseconds of the silent - //! (zero-amplitude) gap between two Partials joined by - //! distillation. Divide by 1000 to use as a member function - //! parameter. This parameter should be the same in Distiller, - //! Sieve, and Collator. - DefaultSilentTimeMs = Distiller::DefaultSilentTimeMs - }; - -// -- construction -- - - //! Construct a new Collator using the specified fade and gap times - //! between Partials. When two Partials are joined, the collated Partial - //! fades out at the end of the earlier Partial and back in again - //! at the onset of the later one. The fade time is the time over - //! which these fades occur. By default, use a 5 ms fade time. - //! The gap time is the additional time over which a Partial faded - //! out must remain at zero amplitude before it can fade back in. - //! By default, use a gap time of one millisecond, to - //! prevent a pair of arbitrarily close null Breakpoints being - //! inserted. (Defaults are copied from the Distiller.) - //! - //! \param partialFadeTime is the time (in seconds) over - //! which Partials joined by distillation fade to - //! and from zero amplitude. Default is 0.005 (one - //! millisecond). - //! \param partialSilentTime is the minimum duration (in seconds) - //! of the silent (zero-amplitude) gap between two - //! Partials joined by distillation. (Default is - //! 0.001 (one millisecond). - explicit - Collator( double partialFadeTime = Collator::DefaultFadeTimeMs/1000.0, - double partialSilentTime = Collator::DefaultSilentTimeMs/1000.0 ); - - // Use compiler-generated copy, assign, and destroy. - -// -- collating -- - - //! Collate unlabeled (zero-labeled) Partials into the smallest-possible - //! number of Partials that does not combine any overlapping Partials. - //! Collated Partials assigned labels higher than any label in the original - //! list, and appear at the end of the sequence, after all previously-labeled - //! Partials. - //! - //! - //! Return an iterator refering to the position of the first collated Partial, - //! or the end of the collated collection if there are no collated Partials. - //! Since collating is in-place, the Partials collection may be smaller - //! (fewer Partials) after collating, and any iterators on the collection - //! may be invalidated. - //! - //! \param partials is the collection of Partials to collate in-place - //! \return the position of the end of the range of labeled Partials, - //! which is either the end of the collection, or the position - //! of the first collated Partial, composed of unlabeled Partials - //! in the original collection. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials - //! must be a PartialList, otherwise it can be any container type - //! storing Partials that supports at least bidirectional iterators. - //! - //! \sa Collator::collate( Container & partials ) -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - typename Container::iterator collate( Container & partials ); -#else - inline - PartialList::iterator collate( PartialList & partials ); -#endif - - //! Function call operator: same as collate( PartialList & partials ). -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - typename Container::iterator operator() ( Container & partials ); -#else - PartialList::iterator operator() ( PartialList & partials ); -#endif - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. Collated Partials are - //! labeled beginning with the label one more than the - //! largest label in the orignal Partials. - //! - //! \param partials is the collection of Partials to collate in-place - //! \param partialFadeTime is the time (in seconds) over - //! which Partials joined by collating fade to - //! and from zero amplitude. - //! \param partialSilentTime is the minimum duration (in seconds) - //! of the silent (zero-amplitude) gap between two - //! Partials joined by collating. - //! \return the position of the first collated Partial - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials - //! must be a PartialList, otherwise it can be any container type - //! storing Partials that supports at least bidirectional iterators. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - static typename Container::iterator - collate( Container & partials, double partialFadeTime, - double partialSilentTime ); -#else - static inline PartialList::iterator - collate( PartialList & partials, double partialFadeTime, - double partialSilentTime ); -#endif - - -private: - -// -- helpers -- - - //! Collate unlabeled (zero labeled) Partials into the smallest - //! possible number of Partials that does not combine any temporally - //! overlapping Partials. Give each collated Partial a label, starting - //! with startlabel, and incrementing. If startLabel is zero, then - //! give each collated Partial the label zero. The unlabeled Partials are - //! collated in-place. - void collateAux( PartialList & unlabled ); - -}; // end of class Collator - -// --------------------------------------------------------------------------- -// collate -// --------------------------------------------------------------------------- -//! Collate unlabeled (zero-labeled) Partials into the smallest-possible -//! number of Partials that does not combine any overlapping Partials. -//! Collated Partials assigned labels higher than any label in the original -//! list, and appear at the end of the sequence, after all previously-labeled -//! Partials. -//! -//! Return an iterator refering to the position of the first collated Partial, -//! or the end of the collated collection if there are no collated Partials. -//! Since collating is in-place, the Partials collection may be smaller -//! (fewer Partials) after collating, and any iterators on the collection -//! may be invalidated. -//! -//! \param partials is the collection of Partials to collate in-place -//! \return the position of the end of the range of labeled Partials, -//! which is either the end of the collection, or the position -//! of the first collated Partial, composed of unlabeled Partials -//! in the original collection. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then partials -//! must be a PartialList, otherwise it can be any container type -//! storing Partials that supports at least bidirectional iterators. -//! -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator -Collator::collate( Container & partials ) -#else -inline -PartialList::iterator -Collator::collate( PartialList & partials ) -#endif -{ -#if ! defined(NO_TEMPLATE_MEMBERS) - typedef typename Container::iterator Iterator; -#else - typedef PartialList::iterator Iterator; -#endif - - // Partition the Partials into labeled and unlabeled, - // and collate the unlabeled ones and replace the - // unlabeled range. - // (This requires bidirectional iterator support.) - Iterator beginUnlabeled = - std::partition( partials.begin(), partials.end(), - std::not1( PartialUtils::isLabelEqual(0) ) ); - // this used to be a stable partition, which - // is very much slower and seems unnecessary - - // cannot splice if this operation is to be generic - // with respect to container, have to copy: - PartialList collated( beginUnlabeled, partials.end() ); - // collated.splice( collated.end(), beginUnlabeled, partials.end() ); - - // determine the label for the first collated Partial: - Partial::label_type labelCollated = 1; - if ( partials.begin() != beginUnlabeled ) - { - labelCollated = - 1 + std::max_element( partials.begin(), beginUnlabeled, - PartialUtils::compareLabelLess() )->label(); - } - if ( labelCollated < 1 ) - { - labelCollated = 1; - } - - // collate unlabeled (zero-labeled) Partials: - collateAux( collated ); - - // label the collated Partials: - for ( Iterator it = collated.begin(); it != collated.end(); ++it ) - { - it->setLabel( labelCollated++ ); - } - - // copy the collated Partials back into the source container - // after the range of labeled Partials - Iterator endCollated = - std::copy( collated.begin(), collated.end(), beginUnlabeled ); - - // remove extra Partials from the end of the source container - if ( endCollated != partials.end() ) - { - typename Iterator::difference_type numLabeled = - std::distance( partials.begin(), beginUnlabeled ); - - partials.erase( endCollated, partials.end() ); - - // restore beginUnlabeled: - beginUnlabeled = partials.begin(); - std::advance( beginUnlabeled, numLabeled ); - } - return beginUnlabeled; -} - -// --------------------------------------------------------------------------- -// Function call operator -// --------------------------------------------------------------------------- -//! Function call operator: same as collate( PartialList & partials ). -//! -//! \sa Collator::collate( Container & partials ) -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator Collator::operator()( Container & partials ) -#else -inline -PartialList::iterator Collator::operator()( PartialList & partials ) -#endif -{ - return collate( partials ); -} - -// --------------------------------------------------------------------------- -// collate -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. Collated Partials are -//! labeled beginning with the label one more than the -//! largest label in the orignal Partials. -//! -//! \post All Partials in the collection are uniquely-labeled, -//! collated Partials are all at the end of the collection -//! (after all labeled Partials). -//! \param partials is the collection of Partials to collate in-place -//! \param partialFadeTime is the time (in seconds) over -//! which Partials joined by collating fade to -//! and from zero amplitude. -//! \param partialSilentTime is the minimum duration (in seconds) -//! of the silent (zero-amplitude) gap between two -//! Partials joined by collateation. (Default is -//! 0.0001 (one tenth of a millisecond). -//! \return the position of the first collated Partial -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then partials -//! must be a PartialList, otherwise it can be any container type -//! storing Partials that supports at least bidirectional iterators. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator -Collator::collate( Container & partials, double partialFadeTime, - double partialSilentTime ) -#else -inline -PartialList::iterator -Collator::collate( PartialList & partials, double partialFadeTime, - double partialSilentTime ) -#endif -{ - Collator instance( partialFadeTime, partialSilentTime ); - return instance.collate( partials ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_COLLATOR_H */ diff --git a/loris_library/Source/src/Dilator.cpp b/loris_library/Source/src/Dilator.cpp deleted file mode 100644 index 733915f..0000000 --- a/loris_library/Source/src/Dilator.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Dilator.C - * - * Implementation of class Dilator. - * - * Kelly Fitz, 26 Oct 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Dilator.h" -#include "Breakpoint.h" -#include "LorisExceptions.h" -#include "Marker.h" -#include "Notifier.h" -#include "Partial.h" -#include "PartialList.h" - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Construct a new Dilator with -//! no time points. -Dilator::Dilator( void ) -{ -} - -// --------------------------------------------------------------------------- -// insert -// --------------------------------------------------------------------------- -//! Insert a pair of initial and target time points. -//! -//! Specify a pair of initial and target time points to be used -//! by this Dilator, corresponding, for example, to the initial -//! and desired time of a particular temporal feature in an -//! analyzed sound. -//! -//! \param i is an initial, or source, time point -//! \param t is a target time point -//! -//! The time points will be sorted before they are used. -//! If, in the sequences of initial and target time points, there are -//! exactly the same number of initial time points preceding i as -//! target time points preceding t, then time i will be warped to -//! time t in the dilation process. -// -void -Dilator::insert( double i, double t ) -{ - _initial.push_back(i); - _target.push_back(t); - - // sort the time points before dilating: - std::sort( _initial.begin(), _initial.end() ); - std::sort( _target.begin(), _target.end() ); -} - -// --------------------------------------------------------------------------- -// warpTime -// -------------------------------------------------------------------------- -//! Return the dilated time value corresponding to the specified initial time. -//! -//! \param currentTime is a pre-dilated time. -//! \return the dilated time corresponding to the initial time currentTime -// -double -Dilator::warpTime( double currentTime ) const -{ - int idx = std::distance( _initial.begin(), - std::lower_bound( _initial.begin(), _initial.end(), currentTime ) ); - Assert( idx == _initial.size() || currentTime <= _initial[idx] ); - - // compute a new time for the Breakpoint at pIter: - double newtime = 0; - if ( idx == 0 ) - { - // all time points in _initial are later than - // the currentTime; stretch if no zero time - // point has been specified, otherwise, shift: - if ( _initial[idx] != 0. ) - newtime = currentTime * _target[idx] / _initial[idx]; - else - newtime = _target[idx] + (currentTime - _initial[idx]); - } - else if ( idx == _initial.size() ) - { - // all time points in _initial are earlier than - // the currentTime; shift: - // - // note: size is already known to be > 0, so - // idx-1 is safe - newtime = _target[idx-1] + (currentTime - _initial[idx-1]); - } - else - { - // currentTime is between the time points at idx and - // idx-1 in _initial; shift and stretch: - // - // note: size is already known to be > 0, so - // idx-1 is safe - Assert( _initial[idx-1] < _initial[idx] ); // currentTime can't wind up - // between two equal times - - double stretch = (_target[idx] - _target[idx-1]) / (_initial[idx] - _initial[idx-1]); - newtime = _target[idx-1] + ((currentTime - _initial[idx-1]) * stretch); - } - - return newtime; -} - -// --------------------------------------------------------------------------- -// dilate -// --------------------------------------------------------------------------- -//! Replace the Partial envelope with a new envelope having the -//! same Breakpoints at times computed to align temporal features -//! in the sorted sequence of initial time points with their -//! counterparts the sorted sequence of target time points. -//! -//! Depending on the specification of initial and target time -//! points, the dilated Partial may have Breakpoints at times -//! less than 0, even if the original Partial did not. -//! -//! It is possible to have duplicate time points in either sequence. -//! Duplicate initial time points result in very localized stretching. -//! Duplicate target time points result in very localized compression. -//! -//! If all initial time points are greater than 0, then an implicit -//! time point at 0 is assumed in both initial and target sequences, -//! so the onset of a sound can be stretched without explcitly specifying a -//! zero point in each vector. (This seems most intuitive, and only looks -//! like an inconsistency if clients are using negative time points in -//! their Dilator, or Partials having Breakpoints before time 0, both -//! of which are probably unusual circumstances.) -//! -//! \param p is the Partial to dilate. -// -void -Dilator::dilate( Partial & p ) const -{ - debugger << "dilating Partial having " << p.numBreakpoints() - << " Breakpoints" << endl; - - // sanity check: - Assert( _initial.size() == _target.size() ); - - // don't dilate if there's no time points, or no Breakpoints: - if ( 0 == _initial.size() || - 0 == p.numBreakpoints() ) - { - return; - } - - // create the new Partial: - Partial newp; - newp.setLabel( p.label() ); - - // timepoint index: - int idx = 0; - for ( Partial::const_iterator iter = p.begin(); iter != p.end(); ++iter ) - { - // find the first initial time point later - // than the currentTime: - double currentTime = iter.time(); - idx = std::distance( _initial.begin(), - std::lower_bound( _initial.begin(), _initial.end(), currentTime ) ); - Assert( idx == _initial.size() || currentTime <= _initial[idx] ); - - // compute a new time for the Breakpoint at pIter: - double newtime = 0; - if ( idx == 0 ) - { - // all time points in _initial are later than - // the currentTime; stretch if no zero time - // point has been specified, otherwise, shift: - if ( _initial[idx] != 0. ) - newtime = currentTime * _target[idx] / _initial[idx]; - else - newtime = _target[idx] + (currentTime - _initial[idx]); - } - else if ( idx == _initial.size() ) - { - // all time points in _initial are earlier than - // the currentTime; shift: - // - // note: size is already known to be > 0, so - // idx-1 is safe - newtime = _target[idx-1] + (currentTime - _initial[idx-1]); - } - else - { - // currentTime is between the time points at idx and - // idx-1 in _initial; shift and stretch: - // - // note: size is already known to be > 0, so - // idx-1 is safe - Assert( _initial[idx-1] < _initial[idx] ); // currentTime can't wind up - // between two equal times - - double stretch = (_target[idx] - _target[idx-1]) / (_initial[idx] - _initial[idx-1]); - newtime = _target[idx-1] + ((currentTime - _initial[idx-1]) * stretch); - } - - // add a Breakpoint at the computed time: - newp.insert( newtime, iter.breakpoint() ); - } - - // new Breakpoints need to be added to the Partial at times corresponding - // to all target time points that are after the first Breakpoint and - // before the last, otherwise, Partials may be briefly out of tune with - // each other, since our Breakpoints are non-uniformly distributed in time: - for ( idx = 0; idx < _initial.size(); ++ idx ) - { - if ( _initial[idx] <= p.startTime() ) - { - continue; - } - else if ( _initial[idx] >= p.endTime() ) - { - break; - } - else - { - newp.insert( _target[idx], - Breakpoint( p.frequencyAt(_initial[idx]), p.amplitudeAt(_initial[idx]), - p.bandwidthAt(_initial[idx]), p.phaseAt(_initial[idx]) ) ); - } - } - - // store the new Partial: - p = newp; -} - - -// --------------------------------------------------------------------------- -// dilate -// --------------------------------------------------------------------------- -//! Compute a new time for the specified Marker using -//! warpTime(), exactly as Partial Breakpoint times are -//! recomputed. This can be used to dilate the Markers -//! corresponding to a collection of Partials. -//! -//! \param m is the Marker whose time should be recomputed. -// -void -Dilator::dilate( Marker & m ) const -{ - m.setTime( warpTime( m.time() ) ); -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Dilator.h b/loris_library/Source/src/Dilator.h deleted file mode 100644 index 3370788..0000000 --- a/loris_library/Source/src/Dilator.h +++ /dev/null @@ -1,410 +0,0 @@ -#ifndef INCLUDE_DILATOR_H -#define INCLUDE_DILATOR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Dilator.h - * - * Definition of class Dilator. - * - * Kelly Fitz, 26 Oct 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if defined(NO_TEMPLATE_MEMBERS) -#include "PartialList.h" -#endif - -#include - -// begin namespace -namespace Loris { - -class Marker; -class Partial; - -// --------------------------------------------------------------------------- -// class Dilator -// -//! Class Dilator represents an algorithm for non-uniformly expanding -//! and contracting the Partial parameter envelopes according to the initial -//! and target (desired) times of temporal features. -//! -//! It is frequently necessary to redistribute temporal events in this way -//! in preparation for a sound morph. For example, when morphing instrument -//! tones, it is common to align the attack, sustain, and release portions -//! of the source sounds by dilating or contracting those temporal regions. -//! -//! This same procedure can be applied to the Markers stored in AiffFile, -//! SdifFile, and SpcFile (see Marker.h). -// -class Dilator -{ -// -- instance variables -- - - std::vector< double > _initial, _target; // time points - -// -- public interface -- -public: -// -- construction -- - - //! Construct a new Dilator with no time points. - Dilator( void ); - - //! Construct a new Dilator using a range of initial time points - //! and a range of target (desired) time points. The client must - //! ensure that the target range has at least as many elements as - //! the initial range. - //! - //! \param ibegin is the beginning of a sequence of initial, or source, - //! time points. - //! \param iend is (one-past) the end of a sequence of initial, or - //! source, time points. - //! \param tbegin is the beginning of a sequence of target time points; - //! this sequence must be as long as the sequence of initial time - //! point described by ibegin and iend. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only const double * arguments. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - Dilator( Iter1 ibegin, Iter1 iend, Iter2 tbegin ); -#else - inline - Dilator( const double * ibegin, const double * iend, const double * tbegin ); -#endif - - // Use compiler-generated copy, assign, and destroy. - -// -- mutation -- - - //! Insert a pair of initial and target time points. - //! - //! Specify a pair of initial and target time points to be used - //! by this Dilator, corresponding, for example, to the initial - //! and desired time of a particular temporal feature in an - //! analyzed sound. - //! - //! \param i is an initial, or source, time point - //! \param t is a target time point - //! - //! The time points will be sorted before they are used. - //! If, in the sequences of initial and target time points, there are - //! exactly the same number of initial time points preceding i as - //! target time points preceding t, then time i will be warped to - //! time t in the dilation process. - void insert( double i, double t ); - -// -- dilation -- - - //! Replace the Partial envelope with a new envelope having the - //! same Breakpoints at times computed to align temporal features - //! in the sorted sequence of initial time points with their - //! counterparts the sorted sequence of target time points. - //! - //! Depending on the specification of initial and target time - //! points, the dilated Partial may have Breakpoints at times - //! less than 0, even if the original Partial did not. - //! - //! It is possible to have duplicate time points in either sequence. - //! Duplicate initial time points result in very localized stretching. - //! Duplicate target time points result in very localized compression. - //! - //! If all initial time points are greater than 0, then an implicit - //! time point at 0 is assumed in both initial and target sequences, - //! so the onset of a sound can be stretched without explcitly specifying a - //! zero point in each vector. (This seems most intuitive, and only looks - //! like an inconsistency if clients are using negative time points in - //! their Dilator, or Partials having Breakpoints before time 0, both - //! of which are probably unusual circumstances.) - //! - //! \param p is the Partial to dilate. - void dilate( Partial & p ) const; - - //! Function call operator: same as dilate( Partial & p ). - void operator() ( Partial & p ) const; - - //! Compute a new time for the specified Marker using - //! warpTime(), exactly as Partial Breakpoint times are - //! recomputed. This can be used to dilate the Markers - //! corresponding to a collection of Partials. - //! - //! \param m is the Marker whose time should be recomputed. - void dilate( Marker & m ) const; - - //! Function call operator: same as dilate( Marker & p ). - void operator() ( Marker & m ) const; - - //! Non-uniformly expand and contract the parameter envelopes of the each - //! Partial in the specified half-open range according to this Dilator's - //! stored initial and target (desired) times. - //! - //! \param dilate_begin is the beginning of a sequence of Partials to dilate. - //! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. Otherwise, this member - //! also works for sequences of Markers. - //! - //! \sa Dilator::dilate( Partial & p ) const - //! \sa Dilator::dilate( Marker & m ) const -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void dilate( Iter dilate_begin, Iter dilate_end ) const; -#else - inline - void dilate( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end ) const; -#endif - - //! Function call operator: same as - //! dilate( Iter dilate_begin, Iter dilate_end ) - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. Otherwise, this member - //! also works for sequences of Markers. - //! - //! \sa Dilator::dilate( Partial & p ) const - //! \sa Dilator::dilate( Marker & m ) const -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void operator() ( Iter dilate_begin, Iter dilate_end ) const; -#else - inline - void operator() ( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end ) const; -#endif - - //! Return the dilated time value corresponding to the specified initial time. - //! - //! \param currentTime is a pre-dilated time. - //! \return the dilated time corresponding to the initial time currentTime - double warpTime( double currentTime ) const; - -// -- static members -- - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Dilator using the specified initial and - //! target times, and apply it to a sequence of Partials. - //! - //! \param dilate_begin is the beginning of a sequence of Partials to dilate. - //! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. - //! \param ibegin is the beginning of a sequence of initial, or source, - //! time points. - //! \param iend is (one-past) the end of a sequence of initial, or - //! source, time points. - //! \param tbegin is the beginning of a sequence of target time points; - //! this sequence must be as long as the sequence of initial time - //! point described by ibegin and iend. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. Otherwise, this member - //! also works for sequences of Markers. - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only const double * arguments for the times, otherwise, any iterator - //! will do.. - //! - //! \sa Dilator::dilate( Partial & p ) const - //! \sa Dilator::dilate( Marker & m ) const -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename PartialsIter, typename TimeIter1, typename TimeIter2 > - static - void dilate( PartialsIter dilate_begin, PartialsIter dilate_end, - TimeIter1 ibegin, TimeIter1 iend, TimeIter2 tbegin ); -#else - static inline - void dilate( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end, - const double * ibegin, const double * iend, - const double * tbegin ); -#endif - -}; // end of class Dilator - - -// --------------------------------------------------------------------------- -// constructor (sequences of time points) -// --------------------------------------------------------------------------- -//! Construct a new Dilator using a range of initial time points -//! and a range of target (desired) time points. The client must -//! ensure that the target range has at least as many elements as -//! the initial range. -//! -//! \param ibegin is the beginning of a sequence of initial, or source, -//! time points. -//! \param iend is (one-past) the end of a sequence of initial, or -//! source, time points. -//! \param tbegin is the beginning of a sequence of target time points; -//! this sequence must be as long as the sequence of initial time -//! point described by ibegin and iend. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only const double * arguments. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -Dilator::Dilator( Iter1 ibegin, Iter1 iend, Iter2 tbegin ) -#else -inline -Dilator::Dilator( const double * ibegin, const double * iend, const double * tbegin ) -#endif -{ - while ( ibegin != iend ) - { - insert( *ibegin++, *tbegin++ ); - } -} - -// --------------------------------------------------------------------------- -// dilate (sequence of Partials or Markers) -// --------------------------------------------------------------------------- -//! Non-uniformly expand and contract the parameter envelopes of the each -//! Partial in the specified half-open range according to this Dilator's -//! stored initial and target (desired) times. -//! -//! \param dilate_begin is the beginning of a sequence of Partials to dilate. -//! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. Otherwise, this member -//! also works for sequences of Markers. -//! -//! \sa Dilator::dilate( Partial & p ) const -//! \sa Dilator::dilate( Marker & m ) const -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Dilator::dilate( Iter dilate_begin, Iter dilate_end ) const -#else -inline -void Dilator::dilate( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end ) const -#endif -{ - while ( dilate_begin != dilate_end ) - { - dilate( *(dilate_begin++) ); - } -} - -// --------------------------------------------------------------------------- -// Function call operator (sequence of Partials or Markers) -// --------------------------------------------------------------------------- -//! Function call operator: same as -//! dilate( Iter dilate_begin, Iter dilate_end ) -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. Otherwise, this member -//! also works for sequences of Markers. -//! -//! \sa Dilator::dilate( Partial & p ) const -//! \sa Dilator::dilate( Marker & m ) const -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Dilator::operator() ( Iter dilate_begin, Iter dilate_end ) const -#else -inline -void Dilator::operator() ( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end ) const -#endif -{ - dilate( dilate_begin, dilate_end ); -} - -// --------------------------------------------------------------------------- -// Function call operator (single Partial) -// --------------------------------------------------------------------------- -//! Function call operator: same as dilate( Partial & p ). -//! -//! \sa Dilator::dilate( Partial & p ) const -// -inline -void Dilator::operator() ( Partial & p ) const -{ - dilate( p ); -} - -// --------------------------------------------------------------------------- -// Function call operator (single Marker) -// --------------------------------------------------------------------------- -//! Function call operator: same as dilate( Marker & m ). -//! -//! \sa Dilator::dilate( Marker & m ) const -// -inline -void Dilator::operator() ( Marker & m ) const -{ - dilate( m ); -} - -// --------------------------------------------------------------------------- -// dilate (static) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! Construct a Dilator using the specified initial and -//! target times, and apply it to a sequence of Partials. -//! -//! \param dilate_begin is the beginning of a sequence of Partials to dilate. -//! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. -//! \param ibegin is the beginning of a sequence of initial, or source, -//! time points. -//! \param iend is (one-past) the end of a sequence of initial, or -//! source, time points. -//! \param tbegin is the beginning of a sequence of target time points; -//! this sequence must be as long as the sequence of initial time -//! point described by ibegin and iend. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. Otherwise, this member -//! also works for sequences of Markers. -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only const double * arguments for the times, otherwise, any iterator -//! will do.. -//! -//! \sa Dilator::dilate( Partial & p ) const -//! \sa Dilator::dilate( Marker & m ) const -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename PartialsIter, typename TimeIter1, typename TimeIter2 > -void Dilator::dilate( PartialsIter dilate_begin, PartialsIter dilate_end, - TimeIter1 ibegin, TimeIter1 iend, TimeIter2 tbegin ) -#else -inline -void Dilator::dilate( PartialList::iterator dilate_begin, - PartialList::iterator dilate_end, - const double * ibegin, const double * iend, - const double * tbegin ) -#endif -{ - Dilator instance( ibegin, iend, tbegin ); - instance.dilate( dilate_begin, dilate_end ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_DILATOR_H */ diff --git a/loris_library/Source/src/Distiller.cpp b/loris_library/Source/src/Distiller.cpp deleted file mode 100644 index 09c9d19..0000000 --- a/loris_library/Source/src/Distiller.cpp +++ /dev/null @@ -1,483 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Distiller.C - * - * Implementation of class Distiller. - * - * Kelly Fitz, 20 Oct 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Distiller.h" -#include "Breakpoint.h" -#include "BreakpointUtils.h" -#include "LorisExceptions.h" -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" -#include "Notifier.h" - -#include -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// Distiller constructor -// --------------------------------------------------------------------------- -//! Construct a new Distiller using the specified fade time -//! for gaps between Partials. When two non-overlapping Partials -//! are distilled into a single Partial, the distilled Partial -//! fades out at the end of the earlier Partial and back in again -//! at the onset of the later one. The fade time is the time over -//! which these fades occur. By default, use a 5 ms fade time. -//! The gap time is the additional time over which a Partial faded -//! out must remain at zero amplitude before it can fade back in. -//! By default, use a gap time of one millisecond, to -//! prevent a pair of arbitrarily close null Breakpoints being -//! inserted. -//! -//! \param partialFadeTime is the time (in seconds) over -//! which Partials joined by distillation fade to -//! and from zero amplitude. Default is 0.005 (one -//! millisecond). -//! \param partialSilentTime is the minimum duration (in seconds) -//! of the silent (zero-amplitude) gap between two -//! Partials joined by distillation. (Default is -//! 0.001 (one millisecond). -// -Distiller::Distiller( double partialFadeTime, double partialSilentTime ) : - _fadeTime( partialFadeTime ), - _gapTime( partialSilentTime ) -{ - if ( _fadeTime <= 0.0 ) - { - Throw( InvalidArgument, "Distiller fade time must be positive." ); - } - if ( _gapTime <= 0.0 ) - { - Throw( InvalidArgument, "Distiller gap time must be positive." ); - } -} - -// -- helpers -- - -// --------------------------------------------------------------------------- -// fadeInAndOut (STATIC) -// --------------------------------------------------------------------------- -// Add zero-amplitude Breakpoints to the ends of a Partial if necessary. -// Do this to all Partials before distilling to make distillation easier. -// -static void fadeInAndOut( Partial & p, double fadeTime ) -{ - if ( p.first().amplitude() != 0 ) - { - p.insert( - p.startTime() - fadeTime, - BreakpointUtils::makeNullBefore( p.first(), fadeTime ) ); - } - - if ( p.last().amplitude() != 0 ) - { - p.insert( - p.endTime() + fadeTime, - BreakpointUtils::makeNullAfter( p.last(), fadeTime ) ); - } -} - -// --------------------------------------------------------------------------- -// merge (STATIC) -// --------------------------------------------------------------------------- -// Merge the Breakpoints in the specified iterator range into the -// distilled Partial. The beginning of the range may overlap, and -// will replace, some non-zero-amplitude portion of the distilled -// Partial. Assume that there is no such overlap at the end of the -// range (could check), because findContribution only leaves overlap -// at the beginning of the range. -// -static void merge( Partial::const_iterator beg, - Partial::const_iterator end, - Partial & destPartial, double fadeTime, - double gapTime = 0. ) -{ - // absorb energy in distilled Partial that overlaps the - // range to merge: - Partial toMerge( beg, end ); - toMerge.absorb( destPartial ); - fadeInAndOut( toMerge, fadeTime ); - - - // find the first Breakpoint in destPartial that is after the - // range of merged Breakpoints, plus the required gap: - Partial::iterator removeEnd = destPartial.findAfter( toMerge.endTime() + gapTime ); - - // if this Breakpoint has non-zero amplitude, need to leave time - // for a fade in: - while ( removeEnd != destPartial.end() && - removeEnd.breakpoint().amplitude() != 0 && - removeEnd.time() < toMerge.endTime() + gapTime + fadeTime ) - { - ++removeEnd; - } - - // find the first Breakpoint in the destination Partial that needs - // to be removed because it is in the overlap region: - Partial::iterator removeBegin = destPartial.findAfter( toMerge.startTime() - gapTime ); - - // if beforeMerge has non-zero amplitude, need to leave time - // for a fade out: - if ( removeBegin != destPartial.begin() ) - { - Partial::iterator beforeMerge = --Partial::iterator(removeBegin); - - while ( removeBegin != destPartial.begin() && - beforeMerge.breakpoint().amplitude() != 0 && - beforeMerge.time() > toMerge.startTime() - gapTime - fadeTime ) - { - --removeBegin; - if ( beforeMerge != destPartial.begin() ) - { - --beforeMerge; - } - } - - } - - // remove the Breakpoints in the merge range from destPartial: - double rbt = (removeBegin != destPartial.end())?(removeBegin.time()):(destPartial.endTime()); - double ret = (removeEnd != destPartial.end())?(removeEnd.time()):(destPartial.endTime()); - Assert( rbt <= ret ); - destPartial.erase( removeBegin, removeEnd ); - - // how about doing the fades here instead? - // fade in if necessary: - if ( removeEnd != destPartial.end() && - removeEnd.breakpoint().amplitude() != 0 ) - { - Assert( removeEnd.time() - fadeTime > toMerge.endTime() ); - - // update removeEnd so that we don't remove this - // null we are inserting: - destPartial.insert( - removeEnd.time() - fadeTime, - BreakpointUtils::makeNullBefore( removeEnd.breakpoint(), fadeTime ) ); - } - - if ( removeEnd != destPartial.begin() ) - { - Partial::iterator beforeMerge = --Partial::iterator(removeEnd); - if ( beforeMerge.breakpoint().amplitude() > 0 ) - { - Assert( beforeMerge.time() + fadeTime < toMerge.startTime() ); - - destPartial.insert( - beforeMerge.time() + fadeTime, - BreakpointUtils::makeNullAfter( beforeMerge.breakpoint(), fadeTime ) ); - } - } - - // insert the Breakpoints in the range: - for ( Partial::const_iterator insert = toMerge.begin(); insert != toMerge.end(); ++insert ) - { - destPartial.insert( insert.time(), insert.breakpoint() ); - } -} - -// --------------------------------------------------------------------------- -// findContribution (STATIC) -// --------------------------------------------------------------------------- -// Find and return an iterator range delimiting the portion of pshort that -// should be spliced into the distilled Partial plong. If any Breakpoint -// falls in a zero-amplitude region of plong, then pshort should contribute, -// AND its onset should be retained (!!! This is the weird part!!!). -// Therefore, if cbeg is not equal to cend, then cbeg is pshort.begin(). -// -std::pair< Partial::iterator, Partial::iterator > -findContribution( Partial & pshort, const Partial & plong, - double fadeTime, double gapTime ) -{ - // a Breakpoint can only fit in the gap if there's - // enough time to fade out pshort, introduce a - // space of length gapTime, and fade in the rest - // of plong (don't need to worry about the fade - // in, because we are checking that plong is zero - // at cbeg.time() + clearance anyway, so the fade - // in must occur after that, and already be part of - // plong): - // - // WRONG if cbeg is before the start of plong. - // Changed so that all Partials are faded in and - // out before distilling, so now the clearance - // need only be the gap time: - double clearance = gapTime; // fadeTime + gapTime; - - Partial::iterator cbeg = pshort.begin(); - while ( cbeg != pshort.end() && - ( plong.amplitudeAt( cbeg.time() ) > 0 || - plong.amplitudeAt( cbeg.time() + clearance ) > 0 ) ) - { - ++cbeg; - } - - Partial::iterator cend = cbeg; - - // if a gap is found, find the end of the - // range of Breakpoints that fit in that - // gap: - while ( cend != pshort.end() && - plong.amplitudeAt( cend.time() ) == 0 && - plong.amplitudeAt( cend.time() + clearance ) == 0 ) - { - ++cend; - } - - // if a gap is found, and it is big enough for at - // least one Breakpoint, then include the - // onset of the Partial: - if ( cbeg != pshort.end() ) - { - cbeg = pshort.begin(); - } - - return std::make_pair( cbeg, cend ); -} - -// --------------------------------------------------------------------------- -// distillSorter (static helper) -// --------------------------------------------------------------------------- -// Helper for sorting Partials for distilling. -// -static bool distillSorter( const Partial & lhs, const Partial & rhs ) -{ - double ldur = lhs.duration(), rdur = rhs.duration(); - if ( ldur != rdur ) - { - return ldur > rdur; - } - else - { - // What to do for same-duration Partials? - // Need to do something consistent, should look - // for energy? - return lhs.startTime() < rhs.startTime(); - /* - double lpeak = PartialUtils::peakAmp( lhs ); - double rpeak = PartialUtils::peakAmp( rhs ); - return lhs > rhs; - */ - } -} - -// --------------------------------------------------------------------------- -// distillOne -// --------------------------------------------------------------------------- -// Distill a list of Partials having a common label -// into a single Partial with that label, and append it -// to the distilled collection. If an empty list of Partials -// is passed, then an empty Partial having the specified -// label is appended. -// -void Distiller::distillOne( PartialList & partials, Partial::label_type label, - PartialList & distilled ) -{ - debugger << "Distiller found " << partials.size() - << " Partials labeled " << label << endl; - - Partial newp; - newp.setLabel( label ); - - if ( partials.size() == 1 ) - { - // trivial if there is only one partial to distill - newp = partials.front(); - } - else if ( partials.size() > 0 ) // it will be an empty Partial otherwise - { - // sort Partials by duration, longer - // Partials will be prefered: - partials.sort( distillSorter ); - - // keep the longest Partial: - PartialList::iterator it = partials.begin(); - newp = *it; - fadeInAndOut( newp, _fadeTime ); - - // Iterate over remaining Partials: - for ( ++it; it != partials.end(); ++it ) - { - fadeInAndOut( *it, _fadeTime ); - - std::pair< Partial::iterator, Partial::iterator > range = - findContribution( *it, newp, _fadeTime, _gapTime ); - Partial::iterator cb = range.first, ce = range.second; - - // There can only be one contributing regions because - // (and only because) the partials are sorted by length - // first! - - // merge Breakpoints into the new Partial, if - // there are any that contribute, otherwise - // just absorb the current Partial as noise: - if ( cb != ce ) - { - // absorb the non-contributing part: - if ( ce != it->end() ) - { - Partial absorbMe( --Partial::iterator(ce), it->end() ); - // shouldn't this just be ce? - newp.absorb( absorbMe ); - - // There cannot be a non-contributing part - // at the beginning of the Partial too, because - // we always retain the beginning of the Partial. - // If findContribution were changed, then - // we might also want to absorb the beginning. - // - // Partial absorbMeToo( it->begin(), cb ); - // newp.absorb( absorbMeToo ); - } - - // merge the contributing part: - merge( cb, ce, newp, _fadeTime, _gapTime ); - } - else - { - // no contribution, absorb the whole thing: - newp.absorb( *it ); - } - } - } - - // take the null Breakpoints off the ends - // should check whether this is appropriate? - // - // This is a bit of a kludge here, sometimes we must - // be inserting more than one null Breakpoint at the - // front end (at least), sometimes shows up as a Partial - // that begins before 0. The idea is to have no nulls at - // the ends, so just remove all nulls at the ends. - while ( 0 < newp.numBreakpoints() && - 0 == newp.begin().breakpoint().amplitude() ) - { - newp.erase( newp.begin() ); - } - - Partial::iterator lastBpPos = newp.end(); - while ( 0 < newp.numBreakpoints() && - 0 == (--lastBpPos).breakpoint().amplitude() ) - { - lastBpPos = newp.erase( lastBpPos ); - } - - // insert the new Partial in the distilled collection - // in label order: - distilled.insert( std::lower_bound( distilled.begin(), distilled.end(), - newp, - PartialUtils::compareLabelLess() ), - newp ); -} - -// --------------------------------------------------------------------------- -// distill_list -// --------------------------------------------------------------------------- -//! Distill labeled Partials in a PartialList leaving only a single -//! Partial per non-zero label. -//! -//! Unlabeled (zero-labeled) Partials are left unmodified at -//! the end of the distilled Partials. -//! -//! Return an iterator refering to the position of the first unlabeled Partial, -//! or the end of the distilled collection if there are no unlabeled Partials. -//! Since distillation is in-place, the Partials collection may be smaller -//! (fewer Partials) after distillation, and any iterators on the collection -//! may be invalidated. -//! -//! \post All labeled Partials in the collection are uniquely-labeled, -//! and all unlabeled Partials have been moved to the end of the -//! sequence. -//! \param partials is the collection of Partials to distill in-place -//! \return the position of the end of the range of distilled Partials, -//! which is either the end of the collection, or the position -//! or the first unlabeled Partial. -// -PartialList::iterator Distiller::distill_list( PartialList & partials ) -{ - // sort the Partials by label, this is why it - // is so much better to distill a list! - partials.sort( PartialUtils::compareLabelLess() ); - - // temporary container of distilled Partials: - PartialList distilled; - - PartialList::iterator lower = partials.begin(); - while ( lower != partials.end() ) - { - Partial::label_type label = lower->label(); - - // identify a sequence of Partials having the same label: - PartialList::iterator upper = - std::find_if( lower, partials.end(), - std::not1( PartialUtils::isLabelEqual( label ) ) ); - - // upper is the first Partial after lower whose label is not - // equal to that of lower. - // [lower, upper) is a range of all the - // partials labeled `label'. - - if ( 0 != label ) - { - // make a container of the Partials having the same - // label, and distill them: - PartialList samelabel; - samelabel.splice( samelabel.begin(), partials, lower, upper ); - distillOne( samelabel, label, distilled ); - } - lower = upper; - } - -#if defined(Debug_Loris) && Debug_Loris - // only unlabeled Partials should remain in partials: - Assert( partials.end() == - std::find_if( partials.begin(), partials.end(), - std::not1( PartialUtils::isLabelEqual( 0 ) ) ) ); -#endif - - // remember where the unlabeled Partials start: - PartialList::iterator beginUnlabeled = partials.begin(); - - // splice in the distilled Partials at the beginning: - partials.splice( partials.begin(), distilled ); - - return beginUnlabeled; -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Distiller.h b/loris_library/Source/src/Distiller.h deleted file mode 100644 index f1672ce..0000000 --- a/loris_library/Source/src/Distiller.h +++ /dev/null @@ -1,370 +0,0 @@ -#ifndef INCLUDE_DISTILLER_H -#define INCLUDE_DISTILLER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Distiller.h - * - * Definition of class Distiller. - * - * Kelly Fitz, 20 Oct 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" - -#include "Notifier.h" // for debugging only - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Distiller -// -//! Class Distiller represents an algorithm for "distilling" a group of -//! Partials that logically represent a single component into a single -//! Partial. -//! -//! The sound morphing algorithm in Loris requires that Partials in a -//! given source be labeled uniquely, that is, no two Partials can have -//! the same label. The Distiller enforces this condition. All Partials -//! identified with a particular frequency channel (see Channelizer), and, -//! therefore, having a common label, are distilled into a single Partial, -//! leaving at most a single Partial per frequency channel and label. -//! Channels that contain no Partials are not represented in the distilled -//! data. Partials that are not labeled, that is, Partials having label 0, -//! are are left unmodified at the end of the Partial sequence. -//! -//! Distillation modifies the Partial container (a PartialList). All -//! Partials in the distilled range having a common label are replaced by -//! a single Partial in the distillation process. Only labeled -//! Partials are affected by distillation. -// -class Distiller -{ -// -- instance variables -- - - double _fadeTime, _gapTime; // distillation parameters - -// -- public interface -- -public: - -// -- global defaults and constants -- - - enum - { - - //! Default time in milliseconds over which Partials joined by - //! distillation fade to and from zero amplitude. Divide by - //! 1000 to use as a member function parameter. This parameter - //! should be the same in Distiller, Sieve, and Collator. - DefaultFadeTimeMs = 5, - - //! Default minimum duration in milliseconds of the silent - //! (zero-amplitude) gap between two Partials joined by - //! distillation. Divide by 1000 to use as a member function - //! parameter. This parameter should be the same in Distiller, - //! Sieve, and Collator. - DefaultSilentTimeMs = 1 - }; - -// -- construction -- - - //! Construct a new Distiller using the specified fade time - //! for gaps between Partials. When two non-overlapping Partials - //! are distilled into a single Partial, the distilled Partial - //! fades out at the end of the earlier Partial and back in again - //! at the onset of the later one. The fade time is the time over - //! which these fades occur. By default, use a 1 ms fade time. - //! The gap time is the additional time over which a Partial faded - //! out must remain at zero amplitude before it can fade back in. - //! By default, use a gap time of one tenth of a millisecond, to - //! prevent a pair of arbitrarily close null Breakpoints being - //! inserted. - //! - //! \param partialFadeTime is the time (in seconds) over - //! which Partials joined by distillation fade to - //! and from zero amplitude. (Default is - //! Distiller::DefaultFadeTime). - //! \param partialSilentTime is the minimum duration (in seconds) - //! of the silent (zero-amplitude) gap between two - //! Partials joined by distillation. (Default is - //! Distiller::DefaultSilentTime). - explicit - Distiller( double partialFadeTime = Distiller::DefaultFadeTimeMs/1000.0, - double partialSilentTime = Distiller::DefaultSilentTimeMs/1000.0 ); - - // Use compiler-generated copy, assign, and destroy. - -// -- distillation -- - - //! Distill labeled Partials in a collection leaving only a single - //! Partial per non-zero label. - //! - //! Unlabeled (zero-labeled) Partials are left unmodified at - //! the end of the distilled Partials. - //! - //! Return an iterator refering to the position of the first unlabeled Partial, - //! or the end of the distilled collection if there are no unlabeled Partials. - //! Since distillation is in-place, the Partials collection may be smaller - //! (fewer Partials) after distillation, and any iterators on the collection - //! may be invalidated. - //! - //! \post All labeled Partials in the collection are uniquely-labeled, - //! and all unlabeled Partials have been moved to the end of the - //! sequence. - //! \param partials is the collection of Partials to distill in-place - //! \return the position of the end of the range of distilled Partials, - //! which is either the end of the collection, or the position - //! or the first unlabeled Partial. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials - //! must be a PartialList, otherwise it can be any container type - //! storing Partials that supports at least bidirectional iterators. - //! - //! \sa Distiller::distill( Container & partials ) -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - typename Container::iterator distill( Container & partials ); -#else - inline - PartialList::iterator distill( PartialList & partials ); -#endif - - //! Function call operator: same as distill( PartialList & partials ). -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - typename Container::iterator operator() ( Container & partials ); -#else - PartialList::iterator operator() ( PartialList & partials ); -#endif - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! - //! \post All labeled Partials in the collection are uniquely-labeled, - //! and all unlabeled Partials have been moved to the end of the - //! sequence. - //! \param partials is the collection of Partials to distill in-place - //! \param partialFadeTime is the time (in seconds) over - //! which Partials joined by distillation fade to - //! and from zero amplitude. - //! \param partialSilentTime is the minimum duration (in seconds) - //! of the silent (zero-amplitude) gap between two - //! Partials joined by distillation. (Default is - //! Distiller::DefaultSilentTime). - //! \return the position of the end of the range of distilled Partials, - //! which is either the end of the collection, or the position - //! or the first unlabeled Partial. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials - //! must be a PartialList, otherwise it can be any container type - //! storing Partials that supports at least bidirectional iterators. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - static typename Container::iterator - distill( Container & partials, double partialFadeTime, - double partialSilentTime = DefaultSilentTimeMs/1000.0 ); -#else - static inline PartialList::iterator - distill( PartialList & partials, double partialFadeTime, - double partialSilentTime = DefaultSilentTimeMs/1000.0 ); -#endif - -private: - -// -- helpers -- - - //! Distill labeled Partials in a PartialList leaving only a single - //! Partial per non-zero label. - //! - //! Unlabeled (zero-labeled) Partials are left unmodified at - //! the end of the distilled Partials. - //! - //! Return an iterator refering to the position of the first unlabeled Partial, - //! or the end of the distilled collection if there are no unlabeled Partials. - //! Since distillation is in-place, the Partials collection may be smaller - //! (fewer Partials) after distillation, and any iterators on the collection - //! may be invalidated. - //! - //! \post All labeled Partials in the collection are uniquely-labeled, - //! and all unlabeled Partials have been moved to the end of the - //! sequence. - //! \param partials is the collection of Partials to distill in-place - //! \return the position of the end of the range of distilled Partials, - //! which is either the end of the collection, or the position - //! or the first unlabeled Partial. - PartialList::iterator distill_list( PartialList & partials ); - - //! Distill a list of Partials having a common label - //! into a single Partial with that label, and append it - //! to the distilled collection. If an empty list of Partials - //! is passed, then an empty Partial having the specified - //! label is appended. - void distillOne( PartialList & partials, Partial::label_type label, - PartialList & distilled ); - -}; // end of class Distiller - -// --------------------------------------------------------------------------- -// distill -// --------------------------------------------------------------------------- -//! Distill labeled Partials in a collection leaving only a single -//! Partial per non-zero label. -//! -//! Unlabeled (zero-labeled) Partials are left unmodified at -//! the end of the distilled Partials. -//! -//! Return an iterator refering to the position of the first unlabeled Partial, -//! or the end of the distilled collection if there are no unlabeled Partials. -//! Since distillation is in-place, the Partials collection may be smaller -//! (fewer Partials) after distillation, and any iterators on the collection -//! may be invalidated. -//! -//! \post All labeled Partials in the collection are uniquely-labeled, -//! and all unlabeled Partials have been moved to the end of the -//! sequence. -//! \param partials is the collection of Partials to distill in-place -//! \return the position of the end of the range of distilled Partials, -//! which is either the end of the collection, or the position -//! or the first unlabeled Partial. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then partials -//! must be a PartialList, otherwise it can be any container type -//! storing Partials that supports at least bidirectional iterators. -//! -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator Distiller::distill( Container & partials ) -{ - // This can be done so much more easily and - // efficiently on a list than on other containers - // that it is worth copying the Partials to a - // list for distillation, and then transfering - // them back. - // - // See below for a specialization for the case - // of the Container being a list, so no copy - // is needed. - PartialList pl( partials.begin(), partials.end() ); - PartialList::iterator it = distill_list( pl ); - - // pl has distilled Partials at beginning, and - // unlabeled Partials at end: - typename Container::iterator beginUnlabeled = - std::copy( pl.begin(), it, partials.begin() ); - - typename Container::iterator endUnlabeled = - std::copy( it, pl.end(), beginUnlabeled ); - - - partials.erase( endUnlabeled, partials.end() ); - - return beginUnlabeled; -} - -// specialization for PartialList container -template< > -inline -PartialList::iterator Distiller::distill( PartialList & partials ) -{ - debugger << "using PartialList version of distill to avoid copying" << endl; - return distill_list( partials ); -} -#else -inline -PartialList::iterator Distiller::distill( PartialList & partials ) -{ - return distill_list( partials ); -} -#endif - -// --------------------------------------------------------------------------- -// Function call operator -// --------------------------------------------------------------------------- -//! Function call operator: same as distill( PartialList & partials ). -//! -//! \sa Distiller::distill( Container & partials ) -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator Distiller::operator()( Container & partials ) -#else -inline -PartialList::iterator Distiller::operator()( PartialList & partials ) -#endif -{ - return distill( partials ); -} - -// --------------------------------------------------------------------------- -// distill -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! -//! \post All labeled Partials in the collection are uniquely-labeled, -//! and all unlabeled Partials have been moved to the end of the -//! sequence. -//! \param partials is the collection of Partials to distill in-place -//! \param partialFadeTime is the time (in seconds) over -//! which Partials joined by distillation fade to -//! and from zero amplitude. -//! \param partialSilentTime is the minimum duration (in seconds) -//! of the silent (zero-amplitude) gap between two -//! Partials joined by distillation. (Default is -//! Distiller::DefaultSilentTime). -//! \return the position of the end of the range of distilled Partials, -//! which is either the end of the collection, or the position -//! or the first unlabeled Partial. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then partials -//! must be a PartialList, otherwise it can be any container type -//! storing Partials that supports at least bidirectional iterators. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Container > -typename Container::iterator -Distiller::distill( Container & partials, double partialFadeTime, - double partialSilentTime ) -#else -inline -PartialList::iterator -Distiller::distill( PartialList & partials, double partialFadeTime, - double partialSilentTime ) -#endif -{ - Distiller instance( partialFadeTime, partialSilentTime ); - return instance.distill( partials ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_DISTILLER_H */ diff --git a/loris_library/Source/src/Envelope.cpp b/loris_library/Source/src/Envelope.cpp deleted file mode 100644 index 019a7c2..0000000 --- a/loris_library/Source/src/Envelope.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Envelope.C - * - * Implementation of class Envelope. - * - * Kelly Fitz, 21 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Envelope.h" - -// Since Envelope is just an interface, there's nothing interesting in -// the implementation file. - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// destructor -// --------------------------------------------------------------------------- -// -Envelope::~Envelope(void) -{ -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Envelope.h b/loris_library/Source/src/Envelope.h deleted file mode 100644 index 832619a..0000000 --- a/loris_library/Source/src/Envelope.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef INCLUDE_ENVELOPE_H -#define INCLUDE_ENVELOPE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Envelope.h - * - * Definition of abstract interface class Envelope. - * - * Kelly Fitz, 21 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include // for autoptr - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Envelope -// -//! Envelope is an base class for objects representing real functions -//! of time. -//! -//! Class Envelope is an abstract base class, specifying interface for -//! prototypable (clonable) objects representing generic, real-valued -//! (double) functions of one real-valued (double) time argument. Derived -//! classes (like BreakpointEnvelope) must implement valueAt() and -//! clone(), the latter to support the Prototype pattern. Clients of -//! Envelope, like Morpher and Distiller, can use prototype Envelopes to -//! make their own private Envelopes. -//! -//! \sa Distiller, Envelope, Morpher -// -class Envelope -{ -// -- public interface -- -public: -// -- construction -- - - // allow compiler to generate constructors - - //! Destroy this Envelope (virtual to allow subclassing). - virtual ~Envelope( void ); - -// -- Envelope interface -- - - //! Return an exact copy of this Envelope (following the Prototype - //! pattern). - virtual Envelope * clone( void ) const = 0; - - //! Return the value of this Envelope at the specified time. - virtual double valueAt( double x ) const = 0; - -}; // end of abstract class Envelope - - -// --------------------------------------------------------------------------- -// class ScaleAndOffsetEnvelope -// -//! ScaleAndOffsetEnvelope is an derived Envelope class for objects -//! representing envelopes having a scale and offset applied (in that order). - -class ScaleAndOffsetEnvelope : public Envelope -{ -// -- public interface -- -public: -// -- construction -- - - //! Construct a new envelope that is a scaled and offset - //! version of another. - ScaleAndOffsetEnvelope( const Envelope & e, double scale, double offset ) : - m_env( e.clone() ), - m_scale( scale ), - m_offset( offset ) - { - } - - //! Construct a copy of an envelope. - ScaleAndOffsetEnvelope( const ScaleAndOffsetEnvelope & rhs ) : - m_env( rhs.m_env->clone() ), - m_scale( rhs.m_scale ), - m_offset( rhs.m_offset ) - { - } - - //! Assignment from another envelope. - ScaleAndOffsetEnvelope & - operator=( const ScaleAndOffsetEnvelope & rhs ) - { - if ( &rhs != this ) - { - m_env.reset( rhs.m_env->clone() ); - m_scale = rhs.m_scale; - m_offset = rhs.m_offset; - } - return *this; - } - -// -- Envelope interface -- - - //! Return an exact copy of this Envelope (following the Prototype - //! pattern). - ScaleAndOffsetEnvelope * clone( void ) const - { - return new ScaleAndOffsetEnvelope( *this ); - } - - //! Return the value of this Envelope at the specified time. - virtual double valueAt( double x ) const - { - return m_offset + ( m_scale * m_env->valueAt( x ) ); - } - -// -- private member variables -- - -private: - - std::auto_ptr< Envelope > m_env; - double m_scale, m_offset; - -}; // end of class ScaleAndOffsetEnvelope - - -// --------------------------------------------------------------------------- -// math operators -// --------------------------------------------------------------------------- - -inline -ScaleAndOffsetEnvelope -operator*( const Envelope & e, double x ) -{ - return ScaleAndOffsetEnvelope( e, x, 0 ); -} - -inline -ScaleAndOffsetEnvelope -operator*( double x, const Envelope & e ) -{ - return e * x; -} - - - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_ENVELOPE_H */ diff --git a/loris_library/Source/src/Exception.h b/loris_library/Source/src/Exception.h deleted file mode 100644 index e21355c..0000000 --- a/loris_library/Source/src/Exception.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef INCLUDE_EXCEPTION_H_DEPRECATED -#define INCLUDE_EXCEPTION_H_DEPRECATED -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Exception.h - * - * This file formerly defined class Exception, a generic exception class, and - * commonly-used derived exception classes, but the name caused build problems - * on case-insensitive systems having a system header called exception.h, so - * the name has been changed to LorisExceptions.h. This file is included as - * legacy support. New code should use LorisExceptions.h. - * - * Kelly Fitz, 17 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "LorisExceptions.h" - -#endif /* ndef INCLUDE_EXCEPTION_H_DEPRECATED */ diff --git a/loris_library/Source/src/F0Estimate.cpp b/loris_library/Source/src/F0Estimate.cpp deleted file mode 100644 index d03c136..0000000 --- a/loris_library/Source/src/F0Estimate.cpp +++ /dev/null @@ -1,697 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * F0Estimate.C - * - * Implementation of an iterative alrogithm for computing an - * estimate of fundamental frequency from a sequence of sinusoidal - * frequencies and amplitudes using a likelihood estimator - * adapted from Quatieri's Speech Signal Processing text. The - * algorithm here takes advantage of the fact that spectral peaks - * have already been identified and extracted in the analysis/modeling - * process. - * - * Kelly Fitz, 28 March 2006 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "F0Estimate.h" - -#include "LorisExceptions.h" // for Assert - -#include "Notifier.h" - -#include -#include -#include - -#include -using std::vector; - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -// #if defined(HAVE_ISFINITE) && (HAVE_ISFINITE) -// using std::isfinite; -// -// isfinite is not, after all, part of the standard, -// it is an extension. If it is not provided, the following -// checks for NaN and finite-ness. -// -// Use this instead. -// This code is taken from -// http://www.johndcook.com/IEEE_exceptions_in_cpp.html - -#include -inline bool IsFiniteNumber( double x ) -{ - // DBL_MAX is defined in float.h. - // Comparisons with NaN always fail. - - return (x <= DBL_MAX && x >= -DBL_MAX); -} - - - - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// forward declarations for helpers, defined below -// Q is the likelihood function, Qprime is its derivative w.r.t. frequency - -static double -secant_method( const vector & amps, - const vector & freqs, - double f1, double f2, - double precision ); - -static void -compute_candidate_freqs( const vector< double > & peak_freqs, - double fmin, double fmax, - vector< double > & eval_freqs ); -static void -evaluate_Q( const vector & amps, - const vector & freqs, - const vector & eval_freqs, - vector & Q ); - -static double -evaluate_Q( const vector & amps, - const vector & freqs, - double eval_freq, - double norm ); - -static double -evaluate_Qprime( const vector & amps, - const vector & freqs, - double eval_freq ); - -static void -evaluate_Q( const vector & amps, - const vector & freqs, - const vector & eval_freqs, - vector & Q, - double norm ); - -// --------------------------------------------------------------------------- - - -// --------------------------------------------------------------------------- -// F0Estimate constructor -// --------------------------------------------------------------------------- -// Construct from parameters of the iterative F0 estimation -// algorithm. Find candidate F0 estimates as integer divisors -// of the peak frequencies, pick the highest frequency of the -// most likely candidates, and refine that estiamte using the -// secant method. -// -// Store the frequency and the normalized value of the -// likelihood function at that frequency (1.0 indicates that -// all the peaks are perfect harmonics of the estimated -// frequency). -// -// See the F0Estimate.h for a description of the algorithm, also -// outlined inline below. - -F0Estimate::F0Estimate( const vector & amps, - const vector & freqs, - double fmin, double fmax, - double resolution ) : - m_frequency( 0 ), - m_confidence( 0 ) -{ - if ( fmin > fmax ) - { - std::swap( fmin, fmax ); - } - // never consider DC (0 Hz) to be a valid fundamental - fmin = std::max( 1., fmin ); - - // ------------------------------------------------------------------------- - // 1) Identify candidate F0s as the integer divisors of the sinusoidal - // frequencies provided, within the specified range (this algorithm - // relies on the reasonable assumption that for any frequency recognized - // as a likely F0, at least one of the sinusoidal frequencies must - // represent a harmonic, the likelihood function makes this same - - // First collect candidate frequencies: all integer - // divisors of the peak frequencies that are between - // fmin and fmax. - vector< double > eval_freqs; - compute_candidate_freqs( freqs, fmin, fmax, eval_freqs ); - - if ( ! eval_freqs.empty() ) - { - // Compute a normalization factor equal to the total - // energy represented by all the peaks passed in - // amps and freqs, so that the value of the likelihood - // function does not depend on the overall signal - // amplitude, but instead depends only on the quality - // of the estimate, or the confidence in the result, - // and the quality of the final estimate can be evaluated - // by the value of the likelihood function. - double normalization = - 1.0 / std::inner_product( amps.begin(), amps.end(), amps.begin(), 0.0 ); - - // Evaluate the likelihood function at the candidate frequencies. - vector < double > Q( eval_freqs.size() ); - evaluate_Q( amps, freqs, eval_freqs, Q, normalization ); - - // ------------------------------------------------------------------------- - // 2) Select the highest frequency candidate that nearly maximizes the - // likelihood function (because all subharmonics of the true F0 will - // be equal in likelihood to the true F0, but no higher frequency can - // be as likely). - - // Find the highest frequency corresponding to a high value of Q - // (the most likely candidate). - - vector::size_type idx = - std::max_element( Q.begin(), Q.end() ) - Q.begin(); - - double bestFreq = eval_freqs[ idx ]; - double bestQ = Q[ idx ]; - - // ------------------------------------------------------------------------- - // 2a) Check the likelihood of integer multiples of the best candidate, - // choose the highest multiple (within the specified range) that - // as likely as the best candidate frequency to be the new best - // candidate. - - // Check integer multiples of the best candidate frequency, - // so that we can be certain that the peak doesn't - // correspond to a subharmonic of the true most-likely - // F0 in the range [fmin,fmax]. - // - // While the next octave up is in range, and its likelihood - // is within 5% of the previously found peak, accept the - // octave as the better candidate (when we reach the true - // best candidate frequency, the next multiple should be - // much less likely). - - double nextF = 2 * bestFreq; - double nextQ = evaluate_Q( amps, freqs, nextF, normalization ); - - while ( fmax > nextF && ( 0.95 * bestQ ) < nextQ ) - { - // update best candidate: - bestFreq = nextF; - bestQ = nextQ; - - // consider the next multiple - nextF += bestFreq; - nextQ = evaluate_Q( amps, freqs, nextF, normalization ); - } - -// notifier << "peak is : " << bestFreq -// << " Hz, Q: " << bestQ << endl; - - // ------------------------------------------------------------------------- - // 3) Refine the best candidate using the secant method for refining the - // root of the derivative of the likelihood function in the neighborhood - // of the best candidate (because a peak in the likelihood function is - // a root of the derivative of that function). - - - // Refine this estimate using the secant method. - // - // Check the derivative function: if the slope (derivative) - // is positive, then assume that bestFreq is just below the - // root, and choose a second frequency just greater than - // bestFreq. Otherwise, assume that bestFreq is just above - // the root of the derivative function, and choose a second - // frequency just below bestFreq. - - double altFreq = bestFreq - resolution; - if ( 0 < evaluate_Qprime( amps, freqs, bestFreq ) ) - { - altFreq = bestFreq + resolution; - } - - // Now invoke the secant method to attempt to refine - // the root estimate: - m_frequency = secant_method( amps, freqs, - bestFreq, altFreq, - resolution ); - - -// notifier << "best candidate is : " << bestFreq -// << " Hz, Q: " << bestQ << endl; -// notifier << "secant method found : " << m_frequency -// << " Hz, Q: " -// << evaluate_Q( amps, freqs, m_frequency, normalization ) << endl; -// - - // What if the secant method flies off to some other root? - // Check that the root is still between fmin and fmax. - if ( m_frequency < fmin || m_frequency > fmax ) - { - // If refining fails, just use the best candidate estimate. - m_frequency = bestFreq; - } - - - // - // Could also use the bisection method, or the false position method, which - // always converge. All that is required is that two points on the - // function (the derivative of the likelihood function, in this case) - // having opposite signs are used to begin the search. So we need - // to first find a nearby freq at which the derivative of Q evaluates - // with the opposite sign as bestFreq. - // - - - // Compute the value of the likelihood function at this frequency. - m_confidence = evaluate_Q( amps, freqs, m_frequency, normalization ); - - // If the secant method makes things worse, then just go with the - // the most likely candidate. - // - // This is a sanity measure, should never happen. - if ( bestQ > m_confidence ) - { - m_confidence = bestQ; - m_frequency = bestFreq; - } - -// notifier << "refined to: " << m_frequency -// << " Hz, Q: " << m_confidence << endl; - - } - -} - - -// --------------------------------------------------------------------------- -// --- local helpers --- -// --------------------------------------------------------------------------- - - -// Collect candidate frequencies in eval_freqs. -// Candidates are all integer divisors -// between fmin and fmax of any frequency in the -// vector of peak frequencies provided. - -static void -compute_candidate_freqs( const vector< double > & peak_freqs, - double fmin, double fmax, - vector< double > & eval_freqs ) -{ - Assert( fmax > fmin ); - - eval_freqs.clear(); - - for ( vector< double >::const_iterator pk = peak_freqs.begin(); - pk != peak_freqs.end(); - ++pk ) - { - // check all integer divisors of *pk - double div = 1; - double f = *pk; - - // reject all the ones greater than fmax - while( f > fmax ) - { - ++div; - f = *pk / div; - } - - // keep the the ones that are between fmin - // and fmax - while( f >= fmin ) - { - eval_freqs.push_back( f ); - ++div; - f = *pk / div; - } - } - - // sort the candidats - sort( eval_freqs.begin(), eval_freqs.end() ); -} - - -// --------------------------------------------------------------------------- -// --- likelihood function evaluation --- -// --------------------------------------------------------------------------- - - -// Qterm is a functor to help compute terms -// in the likelihood function sum. - -struct Qterm -{ - double f0; - Qterm( double f ) : f0(f) {} - - double operator()( double amp, double freq ) const - { - double arg = 2*Pi*freq/f0; - return amp*amp*std::cos(arg); - } -}; - -// evaluate_Q -// -// Evaluate the likelihood function at the specified -// frequency. - -static double -evaluate_Q( const vector & amps, - const vector & freqs, - double eval_freq, - double norm ) -{ - double prod = - std::inner_product( amps.begin(), amps.end(), - freqs.begin(), - 0., - std::plus< double >(), - Qterm( eval_freq ) ); - - return prod * norm; -} - -// evaluate_Q -// -// Evaluate the normalized likelihood function at a range of -// frequencies, return the results in the vector Q. - -static void -evaluate_Q( const vector & amps, - const vector & freqs, - const vector & eval_freqs, - vector & Q ) -{ - Assert( eval_freqs.size() == Q.size() ); - Assert( amps.size() == freqs.size() ); - - // Compute a normalization factor equal to the total - // energy represented by all the peaks passed in - // amps and freqs, so that the value of the likelihood - // function does not depend on the overall signal - // amplitude, but instead depends only on the quality - // of the estimate, or the confidence in the result, - // and the quality of the final estimate can be evaluated - // by the value of the likelihood function. - double etotal = std::inner_product( amps.begin(), amps.end(), amps.begin(), 0.0 ); - double norm = 1.0 / etotal; - - evaluate_Q( amps, freqs, eval_freqs, Q, norm ); -} - - - -// evaluate_Q -// -// Evaluate the normalized likelihood function at a range of -// frequencies, using the normalization factor provided, and -// return the results in the vector Q. - -static void -evaluate_Q( const vector & amps, - const vector & freqs, - const vector & eval_freqs, - vector & Q, - double norm ) -{ - Assert( eval_freqs.size() == Q.size() ); - Assert( amps.size() == freqs.size() ); - - // iterate over the frequencies at which to - // evaluate the likelihood function: - vector::const_iterator freq_it = eval_freqs.begin(); - vector::iterator Q_it = Q.begin(); - while ( freq_it != eval_freqs.end() ) - { - double f = *freq_it; - - double result = evaluate_Q( amps, freqs, f, norm ); - - *Q_it++ = result; - ++freq_it; - } -} - -// --------------------------------------------------------------------------- -// --- likelihood function derivative evaluation --- -// --------------------------------------------------------------------------- - - -// Qprimeterm is a functor to help compute terms -// in the likelihood function derivative sum, used -// in the secant method of root refinement. - -struct Qprimeterm -{ - double f0; - Qprimeterm( double f ) : f0(f) {} - - double operator()( double amp, double freq ) const - { - double arg = 2*Pi*freq/f0; - return amp*amp*std::sin(arg)*arg/f0; - } -}; - - -// evaluate_Qprime -// -// Evaluate the derivative of the likelihood function (w.r.t. frequency) -// at the specified frequency. - -static double -evaluate_Qprime( const vector & amps, - const vector & freqs, - double eval_freq ) -{ - double prod = - std::inner_product( amps.begin(), amps.end(), - freqs.begin(), - 0., - std::plus< double >(), - Qprimeterm( eval_freq ) ); - - return prod; -} - -// --------------------------------------------------------------------------- -// --- secant method of refining a root/peak estimate --- -// --------------------------------------------------------------------------- - -// secant_method -// -// Find roots of the derivative of the likelihood -// function using the secant method, return the -// value of x (frequency) at which the roots is found. - -static double -secant_method( const vector & amps, - const vector & freqs, - double f1, double f2, double precision ) -{ - double xn = f1; - double xnm1 = f2; - double fxnm1 = evaluate_Qprime( amps, freqs, xnm1 ); - - const unsigned int MaxIters = 20; - - unsigned int iters = 0; - double deltax = 0.0; - - // Iterate until delta is small, or blows up, - // or we have iterated too many times. - do - { - double fxn = evaluate_Qprime( amps, freqs, xn ); - - deltax = fxn * (xn - xnm1)/(fxn - fxnm1); - - xnm1 = xn; - xn = xn - deltax; - - fxnm1 = fxn; - - } while( // fabs( deltax ) > precision && - IsFiniteNumber( deltax ) && - ++iters < MaxIters ); - - - // Check whether delta blew up. If it did, revert to the - // previous value of x. - - if ( ! IsFiniteNumber( deltax ) ) - { - xn = xnm1; - } - - return xn; -} - -#if 0 -// --------------------------------------------------------------------------- -// --- local helpers - dumb old way --- -// --------------------------------------------------------------------------- - - -static void -compute_eval_freqs( double fmin, double fmax, - vector & eval_freqs ); - -static vector::const_iterator -choose_peak( const vector & Q ); - -// --------------------------------------------------------------------------- -// F0Estimate constructor -- iterative method -// --------------------------------------------------------------------------- -// Iteratively compute the value of the likelihood function -// at a range of frequencies around the peak likelihood. -// Store the maximum value when the range of likelihood -// values computed is less than the specified resolution. -// Store the frequency and the normalized value of the -// likelihood function at that frequency (1.0 indicates that -// all the peaks are perfect harmonics of the estimated -// frequency). - -void -F0Estimate::construct_iterative_method( const vector & amps, - const vector & freqs, - double fmin, double fmax, - double resolution ) -{ - - // when the frequency range is small, few samples are - // needed, but initially make sure to sample at least - // every 20 Hz. - // Scratch that, 20 Hz isn't fine enough, could miss a - // peak that way, try 2 Hz. There might be some room to - // adjust this parameter to trade off speed for robustness. - int Nsamps = std::max( 8, (int)std::ceil((fmax-fmin)*0.5) ); - vector eval_freqs, Q; - double peak_freq = fmin, peak_Q = 0; - - // invariant: - // the likelihood function for the estimate of the fundamental - // frequency is maximized at some frequency between - // fmin and fmax (stop when that range is smaller - // than the resolution) - do - { - // determine the frequencies at which to evaluate - // the likelihood function - eval_freqs.resize( Nsamps ); - compute_eval_freqs( fmin, fmax, eval_freqs ); - - // evaluate the likelihood function at those - // frequencies: - Q.resize( Nsamps ); - evaluate_Q( amps, freqs, eval_freqs, Q ); - - // find the highest frequency at which the likelihood - // function peaks: - vector::const_iterator peak = choose_peak( Q ); - int peak_idx = peak - Q.begin(); - peak_Q = *peak; - peak_freq = eval_freqs[ peak_idx ]; - - // update search range: - fmin = eval_freqs[ std::max(peak_idx - 1, 0) ]; - fmax = eval_freqs[ std::min(peak_idx + 1, Nsamps - 1) ]; - Nsamps = std::max( 8, (int)std::ceil((fmax-fmin)*0.05) ); - - } while ( (fmax - fmin) > resolution ); - - m_frequency = peak_freq; - m_confidence = peak_Q; -} - -// compute_eval_freqs -// -// Fill the frequency vector with a sampling -// of the range [fmin,fmax]. -// -// (used by dumb old iterative method) -// -static void -compute_eval_freqs( double fmin, double fmax, - vector & eval_freqs ) -{ - Assert( fmax > fmin ); - - double delta = (fmax-fmin)/(eval_freqs.size()-1); - double f = fmin; - vector::iterator it = eval_freqs.begin(); - while( it != eval_freqs.end() ) - { - *it++ = f; - f += delta; - } - eval_freqs.back() = fmax; -} - -// choose_peak -// -// Return the position of last peak that -// in the vector Q. -// -static vector::const_iterator -choose_peak( const vector & Q ) -{ - Assert( !Q.empty() ); - - double Qmax = *std::max_element( Q.begin(), Q.end() ); - vector::const_iterator it = (Q.end()) - 1; - double tmp = *it; - - // this threshold determines how strong the - // highest-frequency peak in the likelihood - // function needs to be relative to the overall - // peak. For strongly periodic signals, this can - // be quite near to 1, but for things that are - // somewhat non-harmonic, setting it too high - // gives octave errors. Cannot tell whether errors - // will be introduced by having it too low. - const double threshold = 0.85 * Qmax; - while( (it != Q.begin()) && ((*it < threshold) || (*it < *(it-1))) ) - { - --it; - tmp = *it; - } - - return it; -} - -#endif - -} // end of namespace Loris diff --git a/loris_library/Source/src/F0Estimate.h b/loris_library/Source/src/F0Estimate.h deleted file mode 100644 index a20e81e..0000000 --- a/loris_library/Source/src/F0Estimate.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef INCLUDE_F0ESTIMATE_H -#define INCLUDE_F0ESTIMATE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * F0Estimate.h - * - * Implementation of an iterative alrogithm for computing an - * estimate of fundamental frequency from a sequence of sinusoidal - * frequencies and amplitudes using a likelihood estimator - * adapted from Quatieri's Speech Signal Processing text. The - * algorithm here takes advantage of the fact that spectral peaks - * have already been identified and extracted in the analysis/modeling - * process. - * - * Kelly Fitz, 28 March 2006 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class F0Estimate -// -//! Represents a configuration of an iterative alrogithm for computing an -//! estimate of fundamental frequency from a sequence of sinusoidal -//! frequencies and amplitudes using a likelihood estimator adapted -//! from Quatieri's Speech Signal Processing text. This algorithm takes -//! advantage of the fact that spectral peaks have already been identified -//! and extracted in the analysis/modeling process. -//! -//! The algorithm consists of the following steps: -//! 1) Identify candidate F0s as the integer divisors of the sinusoidal -//! frequencies provided, within the specified range (this algorithm -//! relies on the reasonable assumption that for any frequency recognized -//! as a likely F0, at least one of the sinusoidal frequencies must -//! represent a harmonic, the likelihood function makes this same -//! assumption) -//! 2) Select the highest frequency candidate (within range) that maximizes -//! the likelihood function (because all subharmonics of the true F0 will -//! be equal in likelihood to the true F0, but no higher frequency can -//! be as likely). -//! 2a) Check the likelihood of integer multiples of the best candidate, -//! choose the highest multiple (within the specified range) that -//! as likely as the best candidate frequency to be the new best -//! candidate. -//! 3) Refine the best candidate using the secant method for refining the -//! root of the derivative of the likelihood function in the neighborhood -//! of the best candidate (because a peak in the likelihood function is -//! a root of the derivative of that function). -// - -class F0Estimate -{ -private: - - double m_frequency; //! estimated fundamental frequency in Hz - double m_confidence; //! normalized confidence for this estimate, - //! equal to 1.0 when all frequencies are perfect - //! harmonics of this estimate's frequency - -public: - - // --- lifecycle --- - - //! Construct from parameters of the iterative F0 estimation - //! algorithm. Find candidate F0 estimates as integer divisors - //! of the peak frequencies, pick the highest frequency of the - //! most likely candidates, and refine that estiamte using the - //! secant method. - //! - //! Store the frequency and the normalized value of the - //! likelihood function at that frequency (1.0 indicates that - //! all the peaks are perfect harmonics of the estimated - //! frequency). - - F0Estimate( const std::vector & amps, - const std::vector & freqs, - double fmin, double fmax, - double resolution ); - - // default copy/assign/destroy are OK - - - // Not sure whether or why these would be useful. - // - // F0Estimate( void ) : m_frequency( 0 ), m_confidence( 0 ) {} - // F0Estimate( double f, double c ) : m_frequency( f ), m_confidence( c ) {} - - - // --- accessors --- - - //! Return the F0 frequency estimate, in Hz, for this estimate. - - double frequency( void ) const { return m_frequency; } - - //! Return the normalized confidence for this estimate, - //! equal to 1.0 when all frequencies are perfect - //! harmonics of this estimate's frequency. - - double confidence( void ) const { return m_confidence; } - - - -}; // end of class F0Estimate - - -} // end of namespace Loris - -#endif // ndef INCLUDE_F0ESTIMATE_H diff --git a/loris_library/Source/src/Filter.cpp b/loris_library/Source/src/Filter.cpp deleted file mode 100644 index c60fddd..0000000 --- a/loris_library/Source/src/Filter.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Filter.C - * - * Implementation of class Loris::Filter, a generic digital filter of - * arbitrary order having both feed-forward and feedback coefficients. - * - * Kelly Fitz, 1 Sept 1999 - * revised 9 Oct 2009 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Filter.h" - -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// default construction -// --------------------------------------------------------------------------- -//! Construct a filter with an all-pass unity gain response. -// -Filter::Filter( void ) : - m_ffwdcoefs( 1, 1.0 ), - m_fbackcoefs( 1, 1.0 ), - m_delayline( 1, 0 ), - m_gain( 1.0 ) -{ -} - -// --------------------------------------------------------------------------- -// copy construction -// --------------------------------------------------------------------------- -//! Make a copy of another digital filter. -//! Do not copy the filter state (delay line). -// -Filter::Filter( const Filter & other ) : - m_delayline( other.m_delayline.size(), 0. ), - m_ffwdcoefs( other.m_ffwdcoefs ), - m_fbackcoefs( other.m_fbackcoefs ), - m_gain( other.m_gain ) -{ - Assert( m_delayline.size() >= m_ffwdcoefs.size() - 1 ); - Assert( m_delayline.size() >= m_fbackcoefs.size() - 1 ); -} - -// --------------------------------------------------------------------------- -// assignment -// --------------------------------------------------------------------------- -//! Make a copy of another digital filter. -//! Do not copy the filter state (delay line). -// -Filter & -Filter::operator=( const Filter & rhs ) -{ - if ( &rhs != this ) - { - m_delayline.resize( rhs.m_delayline.size() ); - clear(); - - m_ffwdcoefs = rhs.m_ffwdcoefs; - m_fbackcoefs = rhs.m_fbackcoefs; - m_gain = rhs.m_gain; - - Assert( m_delayline.size() >= m_ffwdcoefs.size() - 1 ); - Assert( m_delayline.size() >= m_fbackcoefs.size() - 1 ); - } - return *this; -} - -// --------------------------------------------------------------------------- -// destructor -// --------------------------------------------------------------------------- -//! Destructor is virtual to enable subclassing. Subclasses may specialize -//! construction, and may add functionality, but for efficiency, the filtering -//! operation is non-virtual. -// -Filter::~Filter( void ) -{ -} - - -// --------------------------------------------------------------------------- -// apply -// --------------------------------------------------------------------------- -//! Compute a filtered sample from the next input sample. -//! -// -double -Filter::apply( double input ) -{ - // Implement the recurrence relation. m_ffwdcoefs holds the feed-forward - // coefficients, m_fbackcoefs holds the feedback coeffs. The coefficient - // vectors and delay lines are ordered by increasing age. - - double wn = - std::inner_product( m_fbackcoefs.begin()+1, m_fbackcoefs.end(), - m_delayline.begin(), -input ); - // negate input, then negate the inner product - - m_delayline.push_front( wn ); - - double output = std::inner_product( m_ffwdcoefs.begin(), m_ffwdcoefs.end(), - m_delayline.begin(), 0. ); - m_delayline.pop_back(); - - return output * m_gain; -} - -// --- access/mutation --- - -// --------------------------------------------------------------------------- -// numerator -// --------------------------------------------------------------------------- -//! Provide access to the numerator (feed-forward) coefficients -//! of this filter. The coefficients are stored in order of increasing -//! delay (lowest order coefficient first). - -std::vector< double > -Filter::numerator( void ) -{ - return m_ffwdcoefs; -} - -// --------------------------------------------------------------------------- -// numerator -// --------------------------------------------------------------------------- -//! Provide access to the numerator (feed-forward) coefficients -//! of this filter. The coefficients are stored in order of increasing -//! delay (lowest order coefficient first). - -const std::vector< double > -Filter::numerator( void ) const -{ - return m_ffwdcoefs; -} - -// --------------------------------------------------------------------------- -// denominator -// --------------------------------------------------------------------------- -//! Provide access to the denominator (feedback) coefficients -//! of this filter. The coefficients are stored in order of increasing -//! delay (lowest order coefficient first). - -std::vector< double > -Filter::denominator( void ) -{ - return m_fbackcoefs; -} - -// --------------------------------------------------------------------------- -// denominator -// --------------------------------------------------------------------------- -//! Provide access to the denominator (feedback) coefficients -//! of this filter. The coefficients are stored in order of increasing -//! delay (lowest order coefficient first). - -const std::vector< double > -Filter::denominator( void ) const -{ - return m_fbackcoefs; -} - -// --------------------------------------------------------------------------- -// clear -// --------------------------------------------------------------------------- -//! Clear the filter state. -// -void -Filter::clear( void ) -{ - std::fill( m_delayline.begin(), m_delayline.end(), 0 ); -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Filter.h b/loris_library/Source/src/Filter.h deleted file mode 100644 index c4ddfc6..0000000 --- a/loris_library/Source/src/Filter.h +++ /dev/null @@ -1,250 +0,0 @@ -#ifndef INCLUDE_FILTER_H -#define INCLUDE_FILTER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Filter.h - * - * Definition of class Loris::Filter, a generic digital filter of - * arbitrary order having both feed-forward and feedback coefficients. - * - * Kelly Fitz, 1 Sept 1999 - * revised 9 Oct 2009 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "LorisExceptions.h" -#include "Notifier.h" - -#include -#include -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Filter -// -//! Filter is an Direct Form II realization of a filter specified -//! by its difference equation coefficients and (optionally) gain, -//! applied to the filter output (defaults to 1.). Coefficients are -//! specified and stored in order of increasing delay. -//! -//! Implements the rational transfer function -//! -//! -1 -nb -//! b[0] + b[1]z + ... + b[nb] z -//! Y(z) = G ---------------------------------- X(z) -//! -1 -na -//! a[0] + a[1]z + ... + a[na] z -//! -//! where b[k] are the feed forward coefficients, and a[k] are the feedback -//! coefficients. If a[0] is not 1, then both a and b are normalized by a[0]. -//! G is the additional filter gain, and is unity if unspecified. -//! -//! -//! Filter is implemented using a std::deque to store the filter state, -//! and relies on the efficiency of that class. If deque is not implemented -//! using some sort of circular buffer (as it should be -- deque is guaranteed -//! to be efficient for repeated insertion and removal at both ends), then -//! this filter class will be slow. -// -class Filter -{ -public: - -// --- lifecycle --- - - // default construction - //! Construct a filter with an all-pass unity gain response. - Filter( void ); - - // initialized construction - //! Initialize a Filter having the specified coefficients, and - //! order equal to the larger of the two coefficient ranges. - //! Coefficients in the sequences are stored in increasing order - //! (lowest order coefficient first). - //! - //! If template members are allowed, then the coefficients - //! can be stored in any kind of iterator range, otherwise, - //! they must be in an array of doubles. - //! - //! \param ffwdbegin is the beginning of a sequence of feed-forward coefficients - //! \param ffwdend is the end of a sequence of feed-forward coefficients - //! \param fbackbegin is the beginning of a sequence of feedback coefficients - //! \param fbackend is the end of a sequence of feedback coefficients - //! \param gain is an optional gain scale applied to the filtered signal - // -#if !defined(NO_TEMPLATE_MEMBERS) - template - Filter( IterT1 ffwdbegin, IterT1 ffwdend, // feed-forward coeffs - IterT2 fbackbegin, IterT2 fbackend, // feedback coeffs - double gain = 1. ); -#else - Filter( const double * ffwdbegin, const double * ffwdend, // feed-forward coeffs - const double * fbackbegin, const double * fbackend, // feedback coeffs - double gain = 1. ); -#endif - - - // copy constructor - //! Make a copy of another digital filter. - //! Do not copy the filter state (delay line). - Filter( const Filter & other ); - - // assignment operator - //! Make a copy of another digital filter. - //! Do not copy the filter state (delay line). - Filter & operator=( const Filter & rhs ); - - //! Destructor is virtual to enable subclassing. Subclasses may specialize - //! construction, and may add functionality, but for efficiency, the filtering - //! operation is non-virtual. - ~Filter( void ); - - -// --- filtering --- - - //! Compute a filtered sample from the next input sample. - //! - //! \param input is the next input sample - //! \return the next output sample - double apply( double input ); - - //! Function call operator, same as sample(). - //! - //! \sa apply - double operator() ( double input ) { return apply(input); } - -// --- access/mutation --- - - //! Provide access to the numerator (feed-forward) coefficients - //! of this filter. The coefficients are stored in order of increasing - //! delay (lowest order coefficient first). - - std::vector< double > numerator( void ); - - //! Provide access to the numerator (feed-forward) coefficients - //! of this filter. The coefficients are stored in order of increasing - //! delay (lowest order coefficient first). - - const std::vector< double > numerator( void ) const; - - //! Provide access to the denominator (feedback) coefficients - //! of this filter. The coefficients are stored in order of increasing - //! delay (lowest order coefficient first). - - std::vector< double > denominator( void ); - - //! Provide access to the denominator (feedback) coefficients - //! of this filter. The coefficients are stored in order of increasing - //! delay (lowest order coefficient first). - - const std::vector< double > denominator( void ) const; - - - //! Clear the filter state. - void clear( void ); - - -private: - -// --- implementation --- - - //! single delay line for Direct-Form II implementation - std::deque< double > m_delayline; - - //! feed-forward coefficients - std::vector< double > m_ffwdcoefs; - - //! feedback coefficients - std::vector< double > m_fbackcoefs; - - //! filter gain (applied to output) - double m_gain; - -}; // end of class Filter - - - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Initialize a Filter having the specified coefficients, and -//! order equal to the larger of the two coefficient ranges. -//! Coefficients in the sequences are stored in increasing order -//! (lowest order coefficient first). -//! -//! If template members are allowed, then the coefficients -//! can be stored in any kind of iterator range, otherwise, -//! they must be in an array of doubles. -//! -//! \param ffwdbegin is the beginning of a sequence of feed-forward coefficients -//! \param ffwdend is the end of a sequence of feed-forward coefficients -//! \param fbackbegin is the beginning of a sequence of feedback coefficients -//! \param fbackend is the end of a sequence of feedback coefficients -//! \param gain is an optional gain scale applied to the filtered signal -// -#if !defined(NO_TEMPLATE_MEMBERS) -template -Filter::Filter( IterT1 ffwdbegin, IterT1 ffwdend, // feed-forward coeffs - IterT2 fbackbegin, IterT2 fbackend, // feedback coeffs - double gain ) : -#else -inline -Filter::Filter( const double * ffwdbegin, const double * ffwdend, // feed-forward coeffs - const double * fbackbegin, const double * fbackend, // feedback coeffs - double gain ) : -#endif - m_ffwdcoefs( ffwdbegin, ffwdend ), - m_fbackcoefs( fbackbegin, fbackend ), - m_delayline( std::max( ffwdend-ffwdbegin, fbackend-fbackbegin ) - 1, 0. ), - m_gain( gain ) -{ - if ( *fbackbegin == 0. ) - { - Throw( InvalidObject, - "Tried to create a Filter with feeback coefficient at zero delay equal to 0.0" ); - } - - // normalize the coefficients by 1/a[0], if a[0] is not equal to 1.0 - // (already checked for a[0] == 0 above) - if ( *fbackbegin != 1. ) - { - // scale all filter coefficients by a[0]: - std::transform( m_ffwdcoefs.begin(), m_ffwdcoefs.end(), m_ffwdcoefs.begin(), - std::bind2nd( std::divides(), *fbackbegin ) ); - std::transform( m_fbackcoefs.begin(), m_fbackcoefs.end(), m_fbackcoefs.begin(), - std::bind2nd( std::divides(), *fbackbegin ) ); - m_fbackcoefs[0] = 1.; - } -} - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_FILTER_H */ diff --git a/loris_library/Source/src/FourierTransform.cpp b/loris_library/Source/src/FourierTransform.cpp deleted file mode 100644 index 2a29238..0000000 --- a/loris_library/Source/src/FourierTransform.cpp +++ /dev/null @@ -1,641 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * FourierTransform.C - * - * Implementation of class Loris::FourierTransform, providing a simplified - * uniform interface to the FFTW library (www.fftw.org), version 2.1.3 - * or newer (including version 3), or to the General Purpose FFT package - * by Takuya OOURA, http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html if - * FFTW is unavailable. - * - * Kelly Fitz, 2 Jun 2006 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "FourierTransform.h" -#include "LorisExceptions.h" -#include "Notifier.h" - -#include -#include - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = std::acos( -1.0 ); -#endif - -#if defined(HAVE_FFTW3_H) && HAVE_FFTW3_H - #include -#elif defined(HAVE_FFTW_H) && HAVE_FFTW_H - #include -#endif - -// --------------------------------------------------------------------------- -// isPO2 - return true if N is a power of two -// --------------------------------------------------------------------------- -// If out_expon is non-zero, return the exponent in that address. -// -static bool isPO2( unsigned int N, int * out_expon = 0 ) -{ - unsigned int M = 1; - int exp = 0; - while ( M < N ) - { - M *= 2; - ++exp; - } - if ( 0 != out_expon && M == N ) - { - *out_expon = exp; - } - return M == N; -} - -// =========================================================================== -// No longer matters that fftw and this class use the same floating point -// data format. The insulating implementation class now does its job of -// really insulating clients completely from FFTW, by copying data between -// buffers of std::complex< double > and fftw_complex, rather than -// relying on those two complex types to have the same memory layout. -// The overhead of copying is probably not significant, compared to -// the expense of computing the transform. -// -// about complex math functions for fftw_complex: -// -// These functions are all defined as templates in . -// Regrettably, they are all implemented using real() and -// imag() _member_ functions of the template argument, T. -// If they had instead been implemented in terms of the real() -// and imag() (template) free functions, then I could just specialize -// those two for the fftw complex data type, and the other template -// functions would work. Instead, I have to specialize _all_ of -// those functions that I want to use. I hope this was a learning -// experience for someone... In the mean time, the alternative I -// have is to take advantage of the fact that fftw_complex and -// std::complex have the same footprint, so I can just -// cast back and forth between the two types. Its icky, but it -// works, and its a lot faster than converting, and more palatable -// than redefining all those operators. -// -// On the subject of brilliant designs, fftw_complex is defined as -// a typedef of an anonymous struct, as in typedef struct {...} fftw_complex, -// so I cannot forward-declare that type. -// -// In other good news, the planning structure got a slight name change -// in version 3, making it even more important to remove all traces of -// FFTW from the FourierTransform class definition. -// -// =========================================================================== - -// begin namespace -namespace Loris { - -using std::complex; -using std::vector; - -// --- private implementation class --- - -// --------------------------------------------------------------------------- -// FTimpl -// -// Insulating implementation class to insulate clients -// completely from everything about the interaction between -// Loris and FFTW. There is more copying of data between buffers, -// but this is not the expensive part of computing Fourier transforms -// and we don't have to do unsavory things that require std::complex -// and fftw_complex to have the same memory layout (we could even get -// by with single-precision floats in FFTW if necessary). Also got -// rid of lots of shared buffer stuff that just made the implementation -// lots more complicated than necessary. This one is simple, if not -// as memory efficient. -// - -#if defined(HAVE_FFTW3_H) && HAVE_FFTW3_H - -class FTimpl // FFTW version 3 -{ -private: - - fftw_plan plan; - FourierTransform::size_type N; - fftw_complex * ftIn; - fftw_complex * ftOut; - -public: - - // Construct an implementation instance: - // allocate an input buffer, and an output buffer - // and make a plan. - FTimpl( FourierTransform::size_type sz ) : - plan( 0 ), N( sz ), ftIn( 0 ), ftOut( 0 ) - { - // allocate buffers: - ftIn = (fftw_complex *)fftw_malloc( sizeof( fftw_complex ) * N ); - ftOut = (fftw_complex *)fftw_malloc( sizeof( fftw_complex ) * N ); - if ( 0 == ftIn || 0 == ftOut ) - { - fftw_free( ftIn ); - fftw_free( ftOut ); - throw RuntimeError( "cannot allocate Fourier transform buffers" ); - } - - // create a plan: - plan = fftw_plan_dft_1d( N, ftIn, ftOut, FFTW_FORWARD, FFTW_ESTIMATE ); - - // verify: - if ( 0 == plan ) - { - Throw( RuntimeError, "FourierTransform could not make a (fftw) plan." ); - } - } - - // Destroy the implementation instance: - // dump the plan. - ~FTimpl( void ) - { - if ( 0 != plan ) - { - fftw_destroy_plan( plan ); - } - - fftw_free( ftIn ); - fftw_free( ftOut ); - } - - // Copy complex< double >'s from a buffer into ftIn, - // the buffer must be as long as ftIn. - void loadInput( const complex< double > * bufPtr ) - { - for ( FourierTransform::size_type k = 0; k < N; ++k ) - { - ftIn[ k ][0] = bufPtr->real(); // real part - ftIn[ k ][1] = bufPtr->imag(); // imaginary part - ++bufPtr; - } - } - - // Copy complex< double >'s from ftOut into a buffer, - // which must be as long as ftOut. - void copyOutput( complex< double > * bufPtr ) const - { - for ( FourierTransform::size_type k = 0; k < N; ++k ) - { - *bufPtr = complex< double >( ftOut[ k ][0], ftOut[ k ][1] ); - ++bufPtr; - } - } - - // Compute a forward transform. - void forward( void ) - { - fftw_execute( plan ); - } - -}; // end of class FTimpl for FFTW version 3 - -#elif defined(HAVE_FFTW_H) && HAVE_FFTW_H - -// "die hook" for FFTW, which otherwise try to write to a -// non-existent console. -static void fftw_die_Loris( const char * s ) -{ - using namespace std; // exit might be hidden in there - - notifier << "The FFTW library used by Loris has encountered a fatal error: " << s << endl; - exit(EXIT_FAILURE); -} - -class FTimpl // FFTW version 2 -{ -private: - - fftw_plan plan; - FourierTransform::size_type N; - fftw_complex * ftIn; - fftw_complex * ftOut; - -public: - - // Construct an implementation instance: - // allocate an input buffer, and an output buffer - // and make a plan. - FTimpl( FourierTransform::size_type sz ) : - plan( 0 ), N( sz ), ftIn( 0 ), ftOut( 0 ) - { - // allocate buffers: - ftIn = (fftw_complex *)fftw_malloc( sizeof( fftw_complex ) * N ); - ftOut = (fftw_complex *)fftw_malloc( sizeof( fftw_complex ) * N ); - if ( 0 == ftIn || 0 == ftOut ) - { - fftw_free( ftIn ); - fftw_free( ftOut ); - Throw( RuntimeError, "cannot allocate Fourier transform buffers" ); - } - - // create a plan: - plan = fftw_create_plan_specific( N, FFTW_FORWARD, FFTW_ESTIMATE, - ftIn, 1, ftOut, 1 ); - - // verify: - if ( 0 == plan ) - { - Throw( RuntimeError, "FourierTransform could not make a (fftw) plan." ); - } - - // FFTW calls fprintf a lot, which may be a problem in - // non-console-enabled applications. Catch fftw_die() - // calls by routing the error message to our own Notifier - // and exiting, using the function defined above. - // - // (version 2 only) - fftw_die_hook = fftw_die_Loris; - } - - // Destroy the implementation instance: - // dump the plan. - ~FTimpl( void ) - { - if ( 0 != plan ) - { - fftw_destroy_plan( plan ); - } - - fftw_free( ftIn ); - fftw_free( ftOut ); - } - - // Copy complex< double >'s from a buffer into ftIn, - // the buffer must be as long as ftIn. - void loadInput( const complex< double > * bufPtr ) - { - for ( FourierTransform::size_type k = 0; k < N; ++k ) - { - c_re( ftIn[ k ] ) = bufPtr->real(); - c_im( ftIn[ k ] ) = bufPtr->imag(); - ++bufPtr; - } - } - - // Copy complex< double >'s from ftOut into a buffer, - // which must be as long as ftOut. - void copyOutput( complex< double > * bufPtr ) const - { - for ( FourierTransform::size_type k = 0; k < N; ++k ) - { - *bufPtr = complex< double >( c_re( ftOut[ k ] ), c_im( ftOut[ k ] ) ); - ++bufPtr; - } - } - - // Compute a forward transform. - void forward( void ) - { - fftw_one( plan, ftIn, ftOut ); - } - -}; // end of class FTimpl for FFTW version 2 - -#else - -#define SORRY_NO_FFTW 1 - -// function prototype, definition in fftsg.c -extern "C" void cdft(int, int, double *, int *, double *); - -// function prototype, definition below -static void slowDFT( double * in, double * out, int N ); - -// Uses General Purpose FFT (Fast Fourier/Cosine/Sine Transform) Package -// by Takuya OOURA, http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html defined -// in fftsg.c. -// -// In the event that the size is not a power of two, uses a (very) slow -// direct DFT computation, defined below. In this case, the workspace -// array is not used, and the twiddle factor array is used to store the -// transform result. - -class FTimpl // platform-neutral stand-alone implementation -{ -private: - - double * mTxInOut; // input/output buffer for in-place transform - double * mTwiddle; // storage for twiddle factors - int * mWorkspace; // workspace storage - - FourierTransform::size_type N; - - bool mIsPO2; - -public: - - // Construct an implementation instance: - // allocate buffers and workspace, and - // initialize the twiddle factors. - FTimpl( FourierTransform::size_type sz ) : - mTxInOut( 0 ), mTwiddle( 0 ), mWorkspace( 0 ), N( sz ), mIsPO2( isPO2( sz ) ) - { - mTxInOut = new double[ 2*N ]; - // input/output buffer for in-place transform - - if ( mIsPO2 ) - { - mTwiddle = new double[ N/2 ]; - // storage for twiddle factors - - mWorkspace = new int[ 2*int( std::sqrt((double)N) + 0.5 ) ]; - // workspace - - if ( 0 == mTxInOut || 0 == mTwiddle || 0 == mWorkspace ) - { - delete [] mTxInOut; - delete [] mTwiddle; - delete [] mWorkspace; - Throw( RuntimeError, "FourierTransform: could not initialize tranform" ); - } - - mWorkspace[0] = 0; // first time only, triggers setup - // no need to do it now, it will happen the - // first time a transform is computed - // cdft_double( 2*N, -1, mTxInOut, mWorkspace, mTwiddle ); - } - else - { - mTwiddle = new double[ 2*N ]; - // use for result in slowDFT - - if ( 0 == mTxInOut || 0 == mTwiddle ) - { - delete [] mTxInOut; - delete [] mTwiddle; - Throw( RuntimeError, "FourierTransform: could not initialize tranform" ); - } - } - } - - // Destroy the implementation instance: - ~FTimpl( void ) - { - delete [] mTxInOut; - delete [] mTwiddle; - delete [] mWorkspace; - } - - // Copy complex< double >'s from a buffer into ftIn, - // the buffer must be as long as ftIn. - void loadInput( const complex< double > * bufPtr ) - { - for ( FourierTransform::size_type k = 0; k < N; ++k ) - { - mTxInOut[ 2*k ] = bufPtr->real(); - mTxInOut[ 2*k+1 ] = bufPtr->imag(); - ++bufPtr; - } - } - - // Copy complex< double >'s from ftOut into a buffer, - // which must be as long as ftOut. Result might be - // stored in the twiddle factor array if this is not - // power of two length DFT. - void copyOutput( complex< double > * bufPtr ) const - { - double * result = mTxInOut; - if ( !mIsPO2 ) - { - result = mTwiddle; - } - - for ( FourierTransform::size_type k = 0; k < N; ++k ) - { - *bufPtr = complex< double >( result[ 2*k ], result[ 2*k+1 ] ); - ++bufPtr; - } - } - - // Compute a forward transform. - void forward( void ) - { - if ( mIsPO2 ) - { - cdft( 2*N, -1, mTxInOut, mWorkspace, mTwiddle ); - } - else - { - slowDFT( mTxInOut, mTwiddle, N ); - } - } - -}; // end of class platform-neutral stand-alone FTimpl - -#endif - -// --- FourierTransform members --- - -// --------------------------------------------------------------------------- -// FourierTransform constructor -// --------------------------------------------------------------------------- -//! Initialize a new FourierTransform of the specified size. -//! -//! \param len is the length of the transform in samples (the -//! number of samples in the transform) -//! \throw RuntimeError if the necessary buffers cannot be -//! allocated, or there is an error configuring FFTW. -// -FourierTransform::FourierTransform( size_type len ) : - _buffer( len ), - _impl( new FTimpl( len ) ) -{ - // zero: - std::fill( _buffer.begin(), _buffer.end(), 0. ); -} - -// --------------------------------------------------------------------------- -// FourierTransform copy constructor -// --------------------------------------------------------------------------- -//! Initialize a new FourierTransform that is a copy of another, -//! having the same size and the same buffer contents. -//! -//! \param rhs is the instance to copy -//! \throw RuntimeError if the necessary buffers cannot be -//! allocated, or there is an error configuring FFTW. -// -FourierTransform::FourierTransform( const FourierTransform & rhs ) : - _buffer( rhs._buffer ), - _impl( new FTimpl( rhs._buffer.size() ) ) // not copied -{ -} - -// --------------------------------------------------------------------------- -// FourierTransform destructor -// --------------------------------------------------------------------------- -//! Free the resources associated with this FourierTransform. -// -FourierTransform::~FourierTransform( void ) -{ - delete _impl; -} - -// --------------------------------------------------------------------------- -// FourierTransform assignment operator -// --------------------------------------------------------------------------- -//! Make this FourierTransform a copy of another, having -//! the same size and buffer contents. -//! -//! \param rhs is the instance to copy -//! \return a refernce to this instance -//! \throw RuntimeError if the necessary buffers cannot be -//! allocated, or there is an error configuring FFTW. -// -FourierTransform & -FourierTransform::operator=( const FourierTransform & rhs ) -{ - if ( this != &rhs ) - { - _buffer = rhs._buffer; - - // The implementation instance is not assigned, - // but a new one is created. - delete _impl; - _impl = 0; - _impl = new FTimpl( _buffer.size() ); - } - - return *this; -} - -// --------------------------------------------------------------------------- -// size -// --------------------------------------------------------------------------- -//! Return the length of the transform (in samples). -//! -//! \return the length of the transform in samples. -FourierTransform::size_type -FourierTransform::size( void ) const -{ - return _buffer.size(); -} - -// --------------------------------------------------------------------------- -// transform -// --------------------------------------------------------------------------- -//! Compute the Fourier transform of the samples stored in the -//! transform buffer. The samples stored in the transform buffer -//! (accessed by index or by iterator) are replaced by the -//! transformed samples, in-place. -// -void -FourierTransform::transform( void ) -{ - // copy data into the transform input buffer: - _impl->loadInput( &_buffer.front() ); - - // crunch: - _impl->forward(); - - // copy the data out of the transform output buffer: - _impl->copyOutput( &_buffer.front() ); -} - - -// --- slow non-power-of-two DFT implementation --- - -#if defined(SORRY_NO_FFTW) - -// --------------------------------------------------------------------------- -// slowDFT -// --------------------------------------------------------------------------- -// Non-power-of-two DFT implementation. in and out cannot be the same, -// and each is 2*N long, storing interleaved complex numbers. -// This version is only used when FFTW is unavailable. -// -static -void slowDFT( double * in, double * out, int N ) -{ -#if 1 - // slow DFT - // This version of the direct DFT computation is tolerably - // speedy, even for rather long transforms (like 8k). - // There is only one expensive call to std::polar, and - // twiddle factors are updated by multiplying. This - // causes some loss in numerical accuracy, worse for - // longer transforms, but even for 10k long transforms, - // accuracy is within hundredths of a percent in my experiments. - - const std::complex< double > eminj2pioN = - std::polar( 1.0, -2.0 * Pi / N ); - - std::complex< double > Wn = 1; - for ( int n = 0; n < N; ++n ) - { - std::complex< double > Wkn = 1; - std::complex< double > Xkn = 0; - for ( int k = 0; k < N; ++k ) - { - Xkn += std::complex< double >( in[ 2*k ], in[ 2*k+1 ] ) * Wkn; - Wkn *= Wn; - } - - out[ 2*n ] = Xkn.real(); - out[ 2*n+1 ] = Xkn.imag(); - Wn *= eminj2pioN; - } - -#else - // very, very slow - // This version of the direct DFT computation is slightly - // more accurate, increasingly so for longer transforms, - // but it is so much slower (4-5x) that the small improvement - // in accuracy is probably not worth the extra wait. For - // short transforms, the accuracy of both algorithms is - // very high, and for long transforms, this algorithm is - // too slow. - // - // Both algorithms are retained here, so that this - // tradeoff can be re-evaluated if necessary. - - for ( int n = 0; n < N; ++n ) - { - std::complex< double > Xkn = 0; - for ( int k = 0; k < N; ++k ) - { - std::complex< double > Wkn = std::polar( 1.0, -2.0 * Pi * k * n / N ); - Xkn += std::complex< double >( in[ 2*k ], in[ 2*k+1 ] ) * Wkn; - } - - out[ 2*n ] = Xkn.real(); - out[ 2*n+1 ] = Xkn.imag(); - } - -#endif -} - -#endif // defined(SORRY_NO_FFTW) - -} // end of namespace Loris diff --git a/loris_library/Source/src/FourierTransform.h b/loris_library/Source/src/FourierTransform.h deleted file mode 100644 index 34867ee..0000000 --- a/loris_library/Source/src/FourierTransform.h +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef INCLUDE_FOURIERTRANSFORM_H -#define INCLUDE_FOURIERTRANSFORM_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * FourierTransform.h - * - * Definition of class Loris::FourierTransform, providing a simplified - * uniform interface to the FFTW library (www.fftw.org), version 2.1.3 - * or newer (including version 3), or to the General Purpose FFT package - * by Takuya OOURA, http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html if - * FFTW is unavailable. - * - * Kelly Fitz, 2 Jun 2006 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include -#include - -// begin namespace -namespace Loris { - -// insulating implementation class, defined in FourierTransform.C -class FTimpl; - -// --------------------------------------------------------------------------- -// class FourierTransform -// -//! FourierTransform provides a simplified interface to the FFTW library -//! (www.fftw.org). Loris uses the FFTW library to perform efficient -//! Fourier transforms of arbitrary length. Clients store and access -//! the in-place transform data as a sequence of std::complex< double >. -//! Samples are stored in the FourierTransform instance using subscript -//! or iterator access, the transform is computed by the transform member, -//! and the transformed samples replace the input samples, and are -//! accessed by subscript or iterator. FourierTransform computes a complex -//! transform, so it can be used to invert a transform of real samples -//! as well. Uses the standard library complex class, which implements -//! arithmetic operations. -//! -//! Supports FFTW versions 2 and 3. -//! Does not make use of FFTW "wisdom" to speed up transform computation. -//! -//! If FFTW is unavailable, uses instead the General Purpose FFT package -//! by Takuya OOURA, http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html defined -//! in fftsg.c for power-of-two transforms, and a very slow direct DFT -//! implementation for non-PO2 transforms. -// -class FourierTransform -{ -// -- public interface -- -public: - - //! An unsigned integral type large enough - //! to represent the length of any transform. - typedef std::vector< std::complex< double > >::size_type size_type; - - //! The type of a non-const iterator of (complex) transform samples. - typedef std::vector< std::complex< double > >::iterator iterator; - - //! The type of a const iterator of (complex) transform samples. - typedef std::vector< std::complex< double > >::const_iterator const_iterator; - -// --- lifecycle --- - - //! Initialize a new FourierTransform of the specified size. - //! - //! \param len is the length of the transform in samples (the - //! number of samples in the transform) - //! \throw RuntimeError if the necessary buffers cannot be - //! allocated, or there is an error configuring FFTW. - FourierTransform( size_type len ); - - //! Initialize a new FourierTransform that is a copy of another, - //! having the same size and the same buffer contents. - //! - //! \param rhs is the instance to copy - //! \throw RuntimeError if the necessary buffers cannot be - //! allocated, or there is an error configuring FFTW. - FourierTransform( const FourierTransform & rhs ); - - //! Free the resources associated with this FourierTransform. - ~FourierTransform( void ); - -// --- operators --- - - //! Make this FourierTransform a copy of another, having - //! the same size and buffer contents. - //! - //! \param rhs is the instance to copy - //! \return a refernce to this instance - //! \throw RuntimeError if the necessary buffers cannot be - //! allocated, or there is an error configuring FFTW. - FourierTransform & operator= ( const FourierTransform & rhs ); - - -// --- access/mutation --- - - //! Access (read/write) a transform sample by index. - //! Use this member to fill the transform buffer before - //! computing the transform, and to access the samples - //! after computing the transform. (inlined for speed) - //! - //! \param index is the index or rank of the complex - //! transform sample to access. Zero is the first - //! position in the buffer. - //! \return non-const reference to the std::complex< double > - //! at the specified position in the buffer. - std::complex< double > & operator[] ( size_type index ) - { - return _buffer[ index ]; - } - - //! Access (read-only) a transform sample by index. - //! Use this member to fill the transform buffer before - //! computing the transform, and to access the samples - //! after computing the transform. (inlined for speed) - //! - //! \param index is the index or rank of the complex - //! transform sample to access. Zero is the first - //! position in the buffer. - //! \return const reference to the std::complex< double > - //! at the specified position in the buffer. - const std::complex< double > & operator[] ( size_type index ) const - { - return _buffer[ index ]; - } - - //! Return an iterator refering to the beginning of the sequence of - //! complex samples in the transform buffer. - //! - //! \return a non-const iterator refering to the first position - //! in the transform buffer. - iterator begin( void ) - { - return _buffer.begin(); - } - - //! Return an iterator refering to the end of the sequence of - //! complex samples in the transform buffer. - //! - //! \return a non-const iterator refering to one past the last - //! position in the transform buffer. - iterator end( void ) - { - return _buffer.end(); - } - - //! Return a const iterator refering to the beginning of the sequence of - //! complex samples in the transform buffer. - //! - //! \return a const iterator refering to the first position - //! in the transform buffer. - const_iterator begin( void ) const - { - return _buffer.begin(); - } - - //! Return a const iterator refering to the end of the sequence of - //! complex samples in the transform buffer. - //! - //! \return a const iterator refering to one past the last - //! position in the transform buffer. - const_iterator end( void ) const - { - return _buffer.end(); - } - -// --- operations --- - - //! Compute the Fourier transform of the samples stored in the - //! transform buffer. The samples stored in the transform buffer - //! (accessed by index or by iterator) are replaced by the - //! transformed samples, in-place. - void transform( void ); - -// --- inquiry --- - - //! Return the length of the transform (in samples). - //! - //! \return the length of the transform in samples. - size_type size( void ) const ; - -// -- instance variables -- -private: - - //! buffer containing the complex transform input before - //! computing the transform, and the complex transform output - //! after computing the transform - std::vector< std::complex< double > > _buffer; - - // insulating implementation instance (defined in - // FourierTransform.C), conceals interface to FFTW - FTimpl * _impl; - -}; // end of class FourierTransform - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_FOURIERTRANSFORM_H */ diff --git a/loris_library/Source/src/FrequencyReference.cpp b/loris_library/Source/src/FrequencyReference.cpp deleted file mode 100644 index 3561e15..0000000 --- a/loris_library/Source/src/FrequencyReference.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * FrequencyReference.C - * - * Implementation of class FrequencyReference. - * - * Kelly Fitz, 3 Dec 2001 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "FrequencyReference.h" - -#include "Breakpoint.h" -#include "Fundamental.h" -#include "LinearEnvelope.h" -#include "Notifier.h" -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" - -#include -#include - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// createEstimator (static) -// --------------------------------------------------------------------------- -// This class is now a wrapper providing the legacy interface to an improved -// and more flexible fundamental frequency estimator. This function -// constructs and configures an instance of the new estimator that -// provides the functionality of the older (Loris 1.4 through 1.5.2) -// FrequencyReference class. -// - -static const double Range = 50; -static const double Ceiling = 20000; -static const double Floor = -60; -static const double Precision = 0.1; -static const double Confidence = 0.9; -static const double Interval = 0.01; - -FundamentalFromPartials createEstimator( void ) -{ - FundamentalFromPartials eparts; - - eparts.setAmpFloor( Floor ); - eparts.setAmpRange( Range ); - eparts.setFreqCeiling( Ceiling ); - eparts.setPrecision( Precision ); - - return eparts; -} - -// --------------------------------------------------------------------------- -// construction -// --------------------------------------------------------------------------- -//! Construct a new fundamental FrequencyReference derived from the -//! specified half-open (STL-style) range of Partials that lies -//! within the speficied average frequency range. Construct the -//! reference envelope with approximately numSamps points. -//! -//! \param begin The beginning of a range of Partials from which to -//! construct a frequency refence envelope. -//! \param end The end of a range of Partials from which to -//! construct a frequency refence envelope. -//! \param minFreq The minimum expected fundamental frequency. -//! \param maxFreq The maximum expected fundamental frequency. -//! \param numSamps The approximate number of estimate of the -//! fundamental frequency from which to construct the -//! frequency reference envelope. -// -FrequencyReference::FrequencyReference( PartialList::const_iterator begin, - PartialList::const_iterator end, - double minFreq, double maxFreq, - long numSamps ) : - _env( new LinearEnvelope() ) -{ - if ( numSamps < 1 ) - { - Throw( InvalidArgument, "A frequency reference envelope must have a positive number of samples." ); - } - - // sanity: - if ( maxFreq < minFreq ) - { - std::swap( minFreq, maxFreq ); - } - -#ifdef Loris_Debug - debugger << "Finding frequency reference envelope in range " << - debugger << minFreq << " to " << maxFreq << " Hz, from " << - debugger << std::distance(begin,end) << " Partials" << std::endl; -#endif - - - FundamentalFromPartials est = createEstimator(); - std::pair< double, double > span = PartialUtils::timeSpan( begin, end ); - double dt = ( span.second - span.first ) / ( numSamps + 1 ); - *_env = est.buildEnvelope( begin, end, - span.first, span.second, dt, - minFreq, maxFreq, - Confidence ); -} - -// --------------------------------------------------------------------------- -// construction -// --------------------------------------------------------------------------- -//! Construct a new fundamental FrequencyReference derived from the -//! specified half-open (STL-style) range of Partials that lies -//! within the speficied average frequency range. Construct the -//! reference envelope from fundamental estimates taken every -//! five milliseconds. -//! -//! \param begin The beginning of a range of Partials from which to -//! construct a frequency refence envelope. -//! \param end The end of a range of Partials from which to -//! construct a frequency refence envelope. -//! \param minFreq The minimum expected fundamental frequency. -//! \param maxFreq The maximum expected fundamental frequency. -// -FrequencyReference::FrequencyReference( PartialList::const_iterator begin, - PartialList::const_iterator end, - double minFreq, double maxFreq ) : - _env( new LinearEnvelope() ) -{ - // sanity: - if ( maxFreq < minFreq ) - { - std::swap( minFreq, maxFreq ); - } - -#ifdef Loris_Debug - debugger << "Finding frequency reference envelope in range " << - debugger << minFreq << " to " << maxFreq << " Hz, from " << - debugger << std::distance(begin,end) << " Partials" << std::endl; -#endif - - FundamentalFromPartials est = createEstimator(); - std::pair< double, double > span = PartialUtils::timeSpan( begin, end ); - *_env = est.buildEnvelope( begin, end, - span.first, span.second, Interval, - minFreq, maxFreq, - Confidence ); - -} - -// --------------------------------------------------------------------------- -// copy construction -// --------------------------------------------------------------------------- -// -FrequencyReference::FrequencyReference( const FrequencyReference & other ) : - _env( other._env->clone() ) -{ -} - -// --------------------------------------------------------------------------- -// destruction -// --------------------------------------------------------------------------- -// -FrequencyReference::~FrequencyReference() -{ -} - -// --------------------------------------------------------------------------- -// assignment -// --------------------------------------------------------------------------- -// -FrequencyReference & -FrequencyReference::operator = ( const FrequencyReference & rhs ) -{ - if ( &rhs != this ) - { - _env.reset( rhs._env->clone() ); - } - return *this; -} - -// --------------------------------------------------------------------------- -// clone -// --------------------------------------------------------------------------- -// -FrequencyReference * -FrequencyReference::clone( void ) const -{ - return new FrequencyReference( *this ); -} - -// --------------------------------------------------------------------------- -// valueAt -// --------------------------------------------------------------------------- -// -double -FrequencyReference::valueAt( double x ) const -{ - return _env->valueAt(x); -} - -// --------------------------------------------------------------------------- -// envelope -// --------------------------------------------------------------------------- -// Conversion to LinearEnvelope return a BreakpointEnvelope that -// evaluates indentically to this FrequencyReference at all time. -// -LinearEnvelope -FrequencyReference::envelope( void ) const -{ - return *_env; -} - -// --------------------------------------------------------------------------- -// timeOfPeakEnergy (static helper function) -// --------------------------------------------------------------------------- -// Return the time at which the given Partial attains its -// maximum sinusoidal energy. -// -static double timeOfPeakEnergy( const Partial & p ) -{ - Partial::const_iterator partialIter = p.begin(); - double maxAmp = - partialIter->amplitude() * std::sqrt( 1. - partialIter->bandwidth() ); - double time = partialIter.time(); - - for ( ++partialIter; partialIter != p.end(); ++partialIter ) - { - double a = partialIter->amplitude() * - std::sqrt( 1. - partialIter->bandwidth() ); - if ( a > maxAmp ) - { - maxAmp = a; - time = partialIter.time(); - } - } - - return time; -} -// --------------------------------------------------------------------------- -// IsInFrequencyRange -// --------------------------------------------------------------------------- -// Function object for finding Partials that attain their maximum -// sinusoidal energy at a frequency within a specified range. -// -struct IsInFrequencyRange -{ - double minFreq, maxFreq; - IsInFrequencyRange( double min, double max ) : - minFreq( min ), - maxFreq( max ) - { - // sanity: - if ( maxFreq < minFreq ) - std::swap( minFreq, maxFreq ); - } - - bool operator() ( const Partial & p ) - { - double compareFreq = p.frequencyAt( timeOfPeakEnergy( p ) ); - return compareFreq >= minFreq && compareFreq <= maxFreq; - } -}; - - - -} // end of namespace Loris diff --git a/loris_library/Source/src/FrequencyReference.h b/loris_library/Source/src/FrequencyReference.h deleted file mode 100644 index 366c57f..0000000 --- a/loris_library/Source/src/FrequencyReference.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef INCLUDE_FREQUENCYREFERENCE_H -#define INCLUDE_FREQUENCYREFERENCE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * FrequencyReference.h - * - * Definition of class FrequencyReference. - * - * Kelly Fitz, 3 Dec 2001 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Envelope.h" -#include "PartialList.h" -#include - -// begin namespace -namespace Loris { - -class LinearEnvelope; - -// --------------------------------------------------------------------------- -// class FrequencyReference -// -//! Class FrequencyReference represents a reference frequency envelope -//! derived from an estimate of the fundamental frequency of a given range -//! of Partials within in a specified frequency range. This reference envelope -//! can be used for channelizing the Partials in preparation for morphing -//! (see Channelizer.h). -//! -//! FrequencyReference implements the Envelope interface (see -//! Envelope.h). -// -class FrequencyReference : public Envelope -{ -// -- instance variables -- - std::auto_ptr< LinearEnvelope > _env; - -// -- public interface -- -public: -// -- construction -- - - //! Construct a new fundamental FrequencyReference derived from the - //! specified half-open (STL-style) range of Partials that lies - //! within the speficied average frequency range. Construct the - //! reference envelope with approximately numSamps points. - //! - //! \param begin The beginning of a range of Partials from which to - //! construct a frequency refence envelope. - //! \param end The end of a range of Partials from which to - //! construct a frequency refence envelope. - //! \param minFreq The minimum expected fundamental frequency. - //! \param maxFreq The maximum expected fundamental frequency. - //! \param numSamps The approximate number of estimate of the - //! fundamental frequency from which to construct the - //! frequency reference envelope. - FrequencyReference( PartialList::const_iterator begin, - PartialList::const_iterator end, - double minFreq, double maxFreq, long numSamps ); - - //! Construct a new fundamental FrequencyReference derived from the - //! specified half-open (STL-style) range of Partials that lies - //! within the speficied average frequency range. Construct the - //! reference envelope from fundamental estimates taken every - //! five milliseconds. - //! - //! \param begin The beginning of a range of Partials from which to - //! construct a frequency refence envelope. - //! \param end The end of a range of Partials from which to - //! construct a frequency refence envelope. - //! \param minFreq The minimum expected fundamental frequency. - //! \param maxFreq The maximum expected fundamental frequency. - FrequencyReference( PartialList::const_iterator begin, - PartialList::const_iterator end, - double minFreq, double maxFreq ); - - - //! Construct a new FrequencyReference that is an exact copy of the - //! specified FrequencyReference. - FrequencyReference( const FrequencyReference & other ); - - //! Assignment operator: make this FrequencyReference an exact copy - //! of the specified FrequencyReference. - FrequencyReference & operator= ( const FrequencyReference & other ); - - //! Destroy this FrequencyReference. - ~FrequencyReference(); - -// -- conversion to LinearEnvelope -- - - //! Return a LinearEnvelope that evaluates indentically to this - //! FrequencyReference at all time. - LinearEnvelope envelope( void ) const; - -// -- Envelope interface -- - - //! Return an exact copy of this FrequencyReference (following the - //! Prototype pattern). - virtual FrequencyReference * clone( void ) const; - - //! Return the frequency value (in Hz) of this FrequencyReference at the - //! specified time. - virtual double valueAt( double x ) const; - -}; // end of class FrequencyReference - -} // end of namespace Loris - -#endif // ndef INCLUDE_FREQUENCYREFERENCE_H diff --git a/loris_library/Source/src/Fundamental.cpp b/loris_library/Source/src/Fundamental.cpp deleted file mode 100644 index b1c2e8c..0000000 --- a/loris_library/Source/src/Fundamental.cpp +++ /dev/null @@ -1,717 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Fundamental.C - * - * Definition of classes for computing an estimate of time-varying - * fundamental frequency from either a sequence of samples or a - * collection of Partials using a frequency domain maximum likelihood - * algorithm adapted from Quatieri's speech signal processing textbook. - * - * Kelly Fitz, 25 March 2008 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Fundamental.h" - -#include "LorisExceptions.h" -#include "KaiserWindow.h" -#include "LinearEnvelope.h" -#include "Notifier.h" -#include "PartialUtils.h" -#include "ReassignedSpectrum.h" -#include "SpectralPeakSelector.h" - -#include "F0Estimate.h" - -#include -#include -#include - -using namespace std; - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -// begin namespace -namespace Loris { - - - -#define VERIFY_ARG(func, test) \ - do { \ - if (!(test)) \ - Throw( Loris::InvalidArgument, #func ": " #test ); \ - } while (false) - - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- -// FundamentalEstimator members -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- - - -// -- lifecycle -- - -// --------------------------------------------------------------------------- -// constructor (protected) -// --------------------------------------------------------------------------- -//! Construct a new estimator with specified precision and -//! other parameters given default values. -//! -//! The specified precision is used to terminate the iterative -//! estimation procedure. -//! -//! \param precisionHz is the precision in Hz with which the -//! fundamental estimates will be made. - -FundamentalEstimator::FundamentalEstimator( double precisionHz ) : - m_precision( precisionHz ), - m_ampFloor( DefaultAmpFloor ), - m_ampRange( DefaultAmpRange ), - m_freqCeiling( DefaultFreqCeiling ) -{ - VERIFY_ARG( FundamentalEstimator, precisionHz > 0 ); -} - -// --------------------------------------------------------------------------- -// destructor -// --------------------------------------------------------------------------- - -FundamentalEstimator::~FundamentalEstimator( void ) -{ -} - -// -- spectral analysis parameter access -- - -// --------------------------------------------------------------------------- -// ampFloor -// --------------------------------------------------------------------------- -//! Return the absolute amplitude threshold in (negative) dB, -//! below which spectral peaks will not be considered in the -//! estimation of the fundamental (default is 30 dB). -double -FundamentalEstimator::ampFloor( void ) const -{ - return m_ampFloor; -} - -// --------------------------------------------------------------------------- -// ampRange -// --------------------------------------------------------------------------- -//! Return the amplitude range in dB, -//! relative to strongest peak in a frame, floating -//! amplitude threshold below which spectral -//! peaks will not be considered in the estimation of -//! the fundamental (default is 30 dB). -// -double -FundamentalEstimator::ampRange( void ) const -{ - return m_ampRange; -} - -// --------------------------------------------------------------------------- -// freqCeiling -// --------------------------------------------------------------------------- -//! Return the frequency ceiling in Hz, the -//! frequency threshold above which spectral -//! peaks will not be considered in the estimation of -//! the fundamental (default is 10 kHz). -// -double -FundamentalEstimator::freqCeiling( void ) const -{ - return m_freqCeiling; -} - -// --------------------------------------------------------------------------- -// precision -// --------------------------------------------------------------------------- -//! Return the precision of the estimate in Hz, the -//! fundamental frequency will be estimated to -//! within this range (default is 0.1 Hz). -// -double -FundamentalEstimator::precision( void ) const -{ - return m_precision; -} - - -// -- spectral analysis parameter mutation -- - -// --------------------------------------------------------------------------- -// setAmpFloor -// --------------------------------------------------------------------------- -//! Set the absolute amplitude threshold in (negative) dB, -//! below which spectral peaks will not be considered in the -//! estimation of the fundamental (default is 30 dB). -//! -//! \param x is the new value of this parameter. -void -FundamentalEstimator::setAmpFloor( double x ) -{ - VERIFY_ARG( setAmpFloor, x < 0 ); - m_ampFloor = x; -} - -// --------------------------------------------------------------------------- -// setAmpRange -// --------------------------------------------------------------------------- -//! Set the amplitude range in dB, -//! relative to strongest peak in a frame, floating -//! amplitude threshold (negative) below which spectral -//! peaks will not be considered in the estimation of -//! the fundamental (default is 30 dB). -//! -//! \param x is the new value of this parameter. -// -void -FundamentalEstimator::setAmpRange( double x ) -{ - VERIFY_ARG( setAmpRange, x > 0 ); - m_ampRange = x; -} - -// --------------------------------------------------------------------------- -// setFreqCeiling -// --------------------------------------------------------------------------- -//! Set the frequency ceiling in Hz, the -//! frequency threshold above which spectral -//! peaks will not be considered in the estimation of -//! the fundamental (default is 10 kHz). Must be -//! greater than the lower bound. -//! -//! \param x is the new value of this parameter. -// -void -FundamentalEstimator::setFreqCeiling( double x ) -{ - m_freqCeiling = x; -} - -// --------------------------------------------------------------------------- -// setPrecision -// --------------------------------------------------------------------------- -//! Set the precision of the estimate in Hz, the -//! fundamental frequency will be estimated to -//! within this range (default is 0.1 Hz). -//! -//! \param x is the new value of this parameter. -// -void -FundamentalEstimator::setPrecision( double x ) -{ - VERIFY_ARG( setPrecision, x > 0 ); - m_precision = x; -} - - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- -// FundamentalFromSamples members -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- - -// -- lifecycle -- - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Construct a new estimator configured with the given -//! analysis window width (main lobe, zero-to-zero). All other -//! spectrum analysis parameters are computed from the specified -//! window width. -//! -//! The specified precision is used to terminate the iterative -//! estimation procedure. If unspecified, the default value, -//! DefaultPrecisionOver100 * 100 is used. -//! -//! \param windowWidthHz is the main lobe width of the Kaiser -//! analysis window in Hz. -//! -//! \param precisionHz is the precision in Hz with which the -//! fundamental estimates will be made. - -FundamentalFromSamples::FundamentalFromSamples( double winWidthHz, - double precisionHz ) : - m_cacheSampleRate( 0 ), - m_windowWidth( winWidthHz ), - FundamentalEstimator( precisionHz ) -{ - VERIFY_ARG( FundamentalFromSamples, winWidthHz > 0 ); -} - -// --------------------------------------------------------------------------- -// destructor -// --------------------------------------------------------------------------- - -FundamentalFromSamples::~FundamentalFromSamples( void ) -{ -} - -// -- fundamental frequency estimation -- - - - -// --------------------------------------------------------------------------- -// buildEnvelope -// --------------------------------------------------------------------------- -//! Construct a linear envelope from fundamental frequency -//! estimates taken at the specified interval in seconds. -//! - -LinearEnvelope -FundamentalFromSamples::buildEnvelope( const double * sampsBeg, - const double * sampsEnd, - double sampleRate, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ) -{ - // sanity check - if ( tbeg > tend ) - { - std::swap( tbeg, tend ); - } - - LinearEnvelope env; - - std::vector< double > amplitudes, frequencies; - - double time = tbeg; - while ( time < tend ) - { - collectFreqsAndAmps( sampsBeg, sampsEnd-sampsBeg, sampleRate, - frequencies, amplitudes, time ); - if ( ! amplitudes.empty() ) - { - F0Estimate est( amplitudes, frequencies, lowerFreqBound, upperFreqBound, - m_precision ); - - if ( est.confidence() >= confidenceThreshold ) - { - env.insert( time, est.frequency() ); - } - } - - time += interval; - } - - return env; -} - - -// --------------------------------------------------------------------------- -// estimateAt -// --------------------------------------------------------------------------- -//! Return an estimate of the fundamental frequency computed -//! at the specified time. - -FundamentalFromSamples::value_type -FundamentalFromSamples::estimateAt( const double * sampsBeg, - const double * sampsEnd, - double sampleRate, - double time, - double lowerFreqBound, double upperFreqBound ) -{ - std::vector< double > amplitudes, frequencies; - - collectFreqsAndAmps( sampsBeg, sampsEnd-sampsBeg, sampleRate, - frequencies, amplitudes, time ); - - F0Estimate est( amplitudes, frequencies, lowerFreqBound, upperFreqBound, m_precision ); - - return est; -} - -// -- spectral analysis parameter access/mutation -- - -// --------------------------------------------------------------------------- -// windowWidth -// --------------------------------------------------------------------------- -//! Return the frequency-domain main lobe width (in Hz) (measured between -//! zero-crossings) of the analysis window used in spectral -//! analysis. -double FundamentalFromSamples::windowWidth( void ) const -{ - return m_windowWidth; -} - -// --------------------------------------------------------------------------- -// setWindowWidth -// --------------------------------------------------------------------------- -//! Set the frequency-domain main lobe width (in Hz) (measured between -//! zero-crossings) of the analysis window used in spectral -//! analysis. -//! -//! \param x is the new value of this parameter. -void FundamentalFromSamples::setWindowWidth( double x ) -{ - VERIFY_ARG( setWindowWidth, x > 0 ); - m_windowWidth = x; -} - - - -// -- private auxiliary functions -- - -// --------------------------------------------------------------------------- -// buildSpectrumAnalyzer -// --------------------------------------------------------------------------- -//! Construct the ReassignedSpectrum that will be used to perform -//! spectral analysis from which peak frequencies and amplitudes -//! will be drawn. This construction is performed in a lazy fashion, -//! and needs to be done again when certain of the parameters change. -//! -//! The spectrum analyzer cannot be constructed without knowledge of -//! the sample rate, specified in Hz, which is needed to determine the -//! parameters of the analysis window. (The sample rate is cached in -//! this class in order that it be possible to determine whether the -//! spectrum analyzer can be reused from one estimate to another.) -// -void -FundamentalFromSamples::buildSpectrumAnalyzer( double srate ) -{ - // configure the reassigned spectral analyzer, - // always use odd-length windows: - const double sidelobeLevel = - m_ampFloor; // amp floor is negative - double winshape = KaiserWindow::computeShape( sidelobeLevel ); - long winlen = KaiserWindow::computeLength( m_windowWidth / srate, winshape ); - if ( 1 != (winlen % 2) ) - { - ++winlen; - } - - std::vector< double > window( winlen ); - KaiserWindow::buildWindow( window, winshape ); - - std::vector< double > windowDeriv( winlen ); - KaiserWindow::buildTimeDerivativeWindow( windowDeriv, winshape ); - - m_spectrum.reset( new ReassignedSpectrum( window, windowDeriv ) ); - - // remember the sample rate used to build this spectrum - // analyzer: - m_cacheSampleRate = srate; -} - -// --------------------------------------------------------------------------- -// sort_peaks_greater_amplitude -// --------------------------------------------------------------------------- -// predicate used for sorting peaks in order of decreasing amplitude: -static bool sort_peaks_greater_amplitude( const SpectralPeak & lhs, - const SpectralPeak & rhs ) -{ - return lhs.amplitude() > rhs.amplitude(); -} - -// --------------------------------------------------------------------------- -// collectFreqsAndAmps -// --------------------------------------------------------------------------- -//! Perform spectral analysis on a sequence of samples, using -//! an analysis window centered at the specified time in seconds. -//! Collect the frequencies and amplitudes of the peaks and return -//! them in the vectors provided. -// - -void -FundamentalFromSamples::collectFreqsAndAmps( const double * samps, - unsigned long nsamps, - double sampleRate, - std::vector< double > & frequencies, - std::vector< double > & amplitudes, - double time ) -{ - amplitudes.clear(); - frequencies.clear(); - - // build the spectrum analyzer if necessary: - if ( m_cacheSampleRate != sampleRate || - 0 == m_spectrum.get() ) - { - buildSpectrumAnalyzer( sampleRate ); - } - - - // configure the peak selection and partial formation policies: - unsigned long winlen = m_spectrum->window().size(); - const double maxTimeCorrection = 0.25 * winlen / sampleRate; // one-quarter the window width - SpectralPeakSelector selector( sampleRate, maxTimeCorrection ); - - - - // compute reassigned spectrum: - // sampsBegin is the position of the first sample to be transformed, - // sampsEnd is the position after the last sample to be transformed. - // (these computations work for odd length windows only) - unsigned long winMiddle = (unsigned long)( sampleRate * time ); - unsigned long sampsBegin = std::max( long(winMiddle) - long(winlen / 2), 0L ); - unsigned long sampsEnd = std::min( winMiddle + (winlen / 2) + 1, nsamps ); - - if ( winMiddle < sampsEnd ) - { - m_spectrum->transform( samps + sampsBegin, samps + winMiddle, samps + sampsEnd ); - - // extract peaks from the spectrum, no fading: - Peaks peaks = selector.selectPeaks( *m_spectrum ); - - if ( ! peaks.empty() ) - { - // sort the peaks in order of decreasing amplitude - // - // (HEY is there any reason to do this, other than to find the largest?) - //std::sort( peaks.begin(), peaks.end(), sort_peaks_greater_amplitude ); - Peaks::iterator maxpos = std::max_element( peaks.begin(), peaks.end(), sort_peaks_greater_amplitude ); - - // determine the floating amplitude threshold - const double thresh = - std::max( std::pow( 10.0, - 0.05 * - m_ampFloor ), - std::pow( 10.0, - 0.05 * m_ampRange ) * maxpos->amplitude() ); - - // collect amplitudes and frequencies and try to - // estimate the fundamental - for ( Peaks::const_iterator spkpos = peaks.begin(); spkpos != peaks.end(); ++spkpos ) - { - if ( spkpos->amplitude() > thresh && - spkpos->frequency() < m_freqCeiling ) - { - amplitudes.push_back( spkpos->amplitude() ); - frequencies.push_back( spkpos->frequency() ); - } - } - } - } -} - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- -// FundamentalFromPartials members -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Construct a new estimator configured with the given precision. -//! The specified precision is used to terminate the iterative -//! estimation procedure. If unspecified, the default value, -//! DefaultPrecisionOver100 * 100 is used. -//! -//! \param precisionHz is the precision in Hz with which the -//! fundamental estimates will be made. - -FundamentalFromPartials::FundamentalFromPartials( double precisionHz ) : - FundamentalEstimator( precisionHz ) -{ -} - -// --------------------------------------------------------------------------- -// copy constructor -// --------------------------------------------------------------------------- -//! Construct a copy of an estimator. Nothing much to do since this class -//! has no data members. -// - -FundamentalFromPartials::FundamentalFromPartials( const FundamentalFromPartials & rhs ) : - FundamentalEstimator( rhs ) -{ -} - -// --------------------------------------------------------------------------- -// destructor -// --------------------------------------------------------------------------- - -FundamentalFromPartials::~FundamentalFromPartials( void ) -{ -} - -// --------------------------------------------------------------------------- -// assignment -// --------------------------------------------------------------------------- -//! Pass the assignment opertion up to the base class. -// - -FundamentalFromPartials & -FundamentalFromPartials::operator=( const FundamentalFromPartials & rhs ) -{ - FundamentalEstimator::operator=( rhs ); - - return *this; -} - -// -- fundamental frequency estimation -- - -// --------------------------------------------------------------------------- -// buildEnvelope -// --------------------------------------------------------------------------- -//! Construct a linear envelope from fundamental frequency -//! estimates taken at the specified interval in seconds. -//! - -LinearEnvelope -FundamentalFromPartials::buildEnvelope( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ) -{ - // sanity check - if ( tbeg > tend ) - { - std::swap( tbeg, tend ); - } - - LinearEnvelope env; - - std::vector< double > amplitudes, frequencies; - - - - double time = tbeg; - while ( time < tend ) - { - if (!controller->setProgress((time - tbeg) / (tend - tbeg))) - return env; - - collectFreqsAndAmps( begin_partials, end_partials, frequencies, amplitudes, time ); - - if (! amplitudes.empty() ) - { - F0Estimate est( amplitudes, frequencies, lowerFreqBound, upperFreqBound, - m_precision ); - - if ( est.confidence() >= confidenceThreshold ) - { - env.insert( time, est.frequency() ); - } - } - - time += interval; - } - - return env; -} - -// --------------------------------------------------------------------------- -// estimateAt -// --------------------------------------------------------------------------- -//! Return an estimate of the fundamental frequency computed -//! at the specified time. - -FundamentalFromPartials::value_type -FundamentalFromPartials::estimateAt( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double time, - double lowerFreqBound, double upperFreqBound ) -{ - std::vector< double > amplitudes, frequencies; - - collectFreqsAndAmps( begin_partials, end_partials, frequencies, amplitudes, time ); - - F0Estimate est( amplitudes, frequencies, lowerFreqBound, upperFreqBound, m_precision ); - - return est; -} - - -// -- private auxiliary functions -- - -// --------------------------------------------------------------------------- -// collectFreqsAndAmps -// --------------------------------------------------------------------------- -//! Perform spectral analysis on a sequence of samples, using -//! an analysis window centered at the specified time in seconds. -//! Collect the frequencies and amplitudes of the peaks and return -//! them in the vectors provided. -// - -void -FundamentalFromPartials::collectFreqsAndAmps( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - std::vector< double > & frequencies, - std::vector< double > & amplitudes, - double time ) -{ - amplitudes.clear(); - frequencies.clear(); - - if ( begin_partials != end_partials ) - { - // determine the absolute amplitude threshold - double thresh = std::pow( 10.0, - 0.05 * - m_ampFloor ); - - double max_amp = 0; - for ( PartialList::const_iterator it = begin_partials; it != end_partials; ++it ) - { - // compute the sinusoidal amplitude (without bandwidth energy) - double sine_amp = std::sqrt(1 - it->bandwidthAt( time )) * it->amplitudeAt( time ); - double freq = it->frequencyAt( time ); - - if ( sine_amp > thresh && - freq < m_freqCeiling ) - { - amplitudes.push_back( sine_amp ); - frequencies.push_back( freq ); - } - - max_amp = std::max( sine_amp, max_amp ); - } - - // remove quietest ones - this isn't very efficient, - // but it is much faster than making two passes (and - // computing two sequences of sinusoidal amplitudes). - thresh = std::pow( 10.0, - 0.05 * m_ampRange ) * max_amp; - vector< double >::size_type N = amplitudes.size(); - vector< double >::size_type k = 0; - while ( k < N ) - { - if ( amplitudes[k] < thresh ) - { - amplitudes.erase( amplitudes.begin() + k ); - frequencies.erase( frequencies.begin() + k ); - --N; - } - else - { - ++k; - } - } - } - -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Fundamental.h b/loris_library/Source/src/Fundamental.h deleted file mode 100644 index 1865576..0000000 --- a/loris_library/Source/src/Fundamental.h +++ /dev/null @@ -1,738 +0,0 @@ -#ifndef INCLUDE_FUNDAMENTAL_H -#define INCLUDE_FUNDAMENTAL_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Fundamental.h - * - * Definition of classes for computing an estimate of time-varying - * fundamental frequency from either a sequence of samples or a - * collection of Partials using a frequency domain maximum likelihood - * algorithm adapted from Quatieri's speech signal processing textbook. - * - * Kelly Fitz, 25 March 2008 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "../ThreadController.h" -#include "LinearEnvelope.h" -#include "PartialList.h" -#include "F0Estimate.h" - -#include -#include - -// begin namespace -namespace Loris { - -class ReassignedSpectrum; - -// --------------------------------------------------------------------------- -// class FundamentalEstimator -// -//! Base class for fundamental estimation, common storage for member -//! variable parameters, type definitions, and constants. - -class FundamentalEstimator -{ -public: - -// -- types -- - - typedef F0Estimate value_type; - -// -- constants -- - - enum { - - DefaultAmpFloor = -60, //! the default absolute amplitude threshold in dB - - DefaultAmpRange = 30, //! the default floating amplitude threshold in dB - - DefaultFreqCeiling = 4000, //! the default frequency threshold in Hz - - DefaultPrecisionOver100 = 10, //! the default frequency precision in 1/100 Hz - - DefaultMinConfidencePct = 90 //! the default required percent confidence to - //! return an estimate (100 is absolute confidence) - }; - - -// -- lifecycle -- - -protected: - - //! Construct a new estimator with specified precision and - //! other parameters given default values. - //! - //! The specified precision is used to terminate the iterative - //! estimation procedure. - //! - //! \param precisionHz is the precision in Hz with which the - //! fundamental estimates will be made. - FundamentalEstimator( double precisionHz ); - -public: - - //! Destructor - virtual ~FundamentalEstimator( void ); - - - // compiler-generated copy and assignment are OK - - -// -- parameter access -- - - //! Return the absolute amplitude threshold in (negative) dB, - //! below which spectral peaks will not be considered in the - //! estimation of the fundamental (default is 30 dB). - double ampFloor( void ) const; - - //! Return the amplitude range in dB, - //! relative to strongest peak in a frame, floating - //! amplitude threshold (negative) below which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is 30 dB). - double ampRange( void ) const; - - //! Return the frequency ceiling in Hz, the - //! frequency threshold above which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is 10 kHz). - double freqCeiling( void ) const; - - //! Return the precision of the estimate in Hz, the - //! fundamental frequency will be estimated to - //! within this range (default is 0.1 Hz). - double precision( void ) const; - -// -- parameter mutation -- - - //! Set the absolute amplitude threshold in (negative) dB, - //! below which spectral peaks will not be considered in the - //! estimation of the fundamental (default is 30 dB). - //! - //! \param x is the new value of this parameter. - void setAmpFloor( double x ); - - //! Set the amplitude range in dB, - //! relative to strongest peak in a frame, floating - //! amplitude threshold (negative) below which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is 30 dB). - //! - //! \param x is the new value of this parameter. - void setAmpRange( double x ); - - //! Set the frequency ceiling in Hz, the - //! frequency threshold above which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is 10 kHz). Must be - //! greater than the lower bound. - //! - //! \param x is the new value of this parameter. - void setFreqCeiling( double x ); - - //! Set the precision of the estimate in Hz, the - //! fundamental frequency will be estimated to - //! within this range (default is 0.1 Hz). - //! - //! \param x is the new value of this parameter. - void setPrecision( double x ); - - -protected: - -// -- parameter member variables -- - - - double m_precision; //! in Hz, fundamental frequency will be estimated to - //! within this range (default is 0.1 Hz) - - double m_ampFloor; //! absolute amplitude threshold below which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is equivalent to 60 dB - //! quieter than a full scale sinusoid) - - double m_ampRange; //! floating amplitude threshold relative to the peak - //! having the largest magnitude below which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is equivalent to 30 dB) - - double m_freqCeiling; //! in Hz, frequency threshold above which spectral - //! peaks will not be considered in the estimation of - //! the fundamental (default is 10 kHz) - - -}; // end of base class FundamentalEstimator - - - -// --------------------------------------------------------------------------- -// class FundamentalFromSamples -// -//! Class FundamentalFromSamples represents an algorithm for -//! time-varying fundamental frequency estimation based on -//! time-frequency reassigned spectral analysis of a sequence -//! of samples. This class is adapted from the Analyzer class -//! (see Analyzer.h), and performs the same spectral analysis -//! and peak extraction, but does not form Partials. -//! -//! For more information about Reassigned Bandwidth-Enhanced -//! Analysis and the Reassigned Bandwidth-Enhanced Additive Sound -//! Model, refer to the Loris website: www.cerlsoundgroup.org/Loris/. -// -class FundamentalFromSamples : public FundamentalEstimator -{ -// -- public interface -- - -public: - -// -- lifecycle -- - - //! Construct a new estimator configured with the given - //! analysis window width (main lobe, zero-to-zero). All other - //! spectrum analysis parameters are computed from the specified - //! window width. - //! - //! The specified precision is used to terminate the iterative - //! estimation procedure. If unspecified, the default value, - //! DefaultPrecisionOver100 * 100 is used. - //! - //! \param windowWidthHz is the main lobe width of the Kaiser - //! analysis window in Hz. - //! - //! \param precisionHz is the precision in Hz with which the - //! fundamental estimates will be made. - FundamentalFromSamples( double winWidthHz, - double precisionHz = DefaultPrecisionOver100 * 0.01 ); - - - - //! Destructor - ~FundamentalFromSamples( void ); - -// -- fundamental frequency estimation -- - - // buildEnvelope - // - //! Construct a linear envelope from fundamental frequency - //! estimates taken at the specified interval in seconds - //! starting at tbeg (seconds) and ending before tend (seconds). - //! - //! \param samps is the beginning of a sequence of samples - //! \param sampsEnd is the end of the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param tbeg is the beginning of the time interval (in seconds) - //! \param tend is the end of the time interval (in seconds) - //! \param interval is the time between breakpoints in the - //! fundamental frequency envelope (in seconds) - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param confidenceThreshold is the minimum confidence level - //! resuired for a fundamental frequency estimate to be - //! added to the envelope. Lower confidence estimates are - //! not added, the envelope returned will not contain - //! breakpoints at times associated with low confidence - //! estimates - //! \return a LinearEnvelope composed of breakpoints corresponding to - //! the fundamental frequency estimates at samples of the span - //! tbeg to tend at the specified sampling interval, only estimates - //! having confidence level exceeding the specified confidence - //! threshold are added to the envelope - LinearEnvelope buildEnvelope( const double * sampsBeg, - const double * sampsEnd, - double sampleRate, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ); - - // buildEnvelope - // - //! Construct a linear envelope from fundamental frequency - //! estimates taken at the specified interval in seconds - //! starting at tbeg (seconds) and ending before tend (seconds). - //! - //! \param samps is the beginning of a sequence of samples - //! \param nsamps is the length of the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param tbeg is the beginning of the time interval (in seconds) - //! \param tend is the end of the time interval (in seconds) - //! \param interval is the time between breakpoints in the - //! fundamental frequency envelope (in seconds) - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param confidenceThreshold is the minimum confidence level - //! resuired for a fundamental frequency estimate to be - //! added to the envelope. Lower confidence estimates are - //! not added, the envelope returned will not contain - //! breakpoints at times associated with low confidence - //! estimates - //! \return a LinearEnvelope composed of breakpoints corresponding to - //! the fundamental frequency estimates at samples of the span - //! tbeg to tend at the specified sampling interval, only estimates - //! having confidence level exceeding the specified confidence - //! threshold are added to the envelope - LinearEnvelope buildEnvelope( const double * sampsBeg, - unsigned long nsamps, - double sampleRate, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ) - { - return buildEnvelope( sampsBeg, sampsBeg + nsamps, sampleRate, - tbeg, tend, interval, - lowerFreqBound, upperFreqBound, - confidenceThreshold ); - } - - - // buildEnvelope - // - //! Construct a linear envelope from fundamental frequency - //! estimates taken at the specified interval in seconds - //! starting at tbeg (seconds) and ending before tend (seconds). - //! - //! \param samps is the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param tbeg is the beginning of the time interval (in seconds) - //! \param tend is the end of the time interval (in seconds) - //! \param interval is the time between breakpoints in the - //! fundamental frequency envelope (in seconds) - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param confidenceThreshold is the minimum confidence level - //! resuired for a fundamental frequency estimate to be - //! added to the envelope. Lower confidence estimates are - //! not added, the envelope returned will not contain - //! breakpoints at times associated with low confidence - //! estimates - //! \return a LinearEnvelope composed of breakpoints corresponding to - //! the fundamental frequency estimates at samples of the span - //! tbeg to tend at the specified sampling interval, only estimates - //! having confidence level exceeding the specified confidence - //! threshold are added to the envelope - LinearEnvelope buildEnvelope( const std::vector< double > & samps, - double sampleRate, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ) - { - return buildEnvelope( &samps[0], &samps[0] + samps.size(), sampleRate, - tbeg, tend, interval, - lowerFreqBound, upperFreqBound, - confidenceThreshold ); - } - - - // estimateAt - // - //! Return an estimate of the fundamental frequency computed - //! at the specified time. The F0Estimate returned stores the - //! estimate of the fundamental frequency (in Hz) and the - //! relative confidence (from 0 to 1) associated with that - //! estimate. - //! - //! \param sampsBeg is the beginning of a sequence of samples - //! \param sampsEnd is the end of the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param time is the time in seconds at which to attempt to estimate - //! the fundamental frequency - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \return the estimate of fundamental frequency in Hz and the - //! confidence associated with that estimate (see - //! F0Estimate.h) - - value_type estimateAt( const double * sampsBeg, - const double * sampsEnd, - double sampleRate, - double time, - double lowerFreqBound, double upperFreqBound ); - - // estimateAt - // - //! Return an estimate of the fundamental frequency computed - //! at the specified time. The F0Estimate returned stores the - //! estimate of the fundamental frequency (in Hz) and the - //! relative confidence (from 0 to 1) associated with that - //! estimate. - //! - //! \param samps is the beginning of a sequence of samples - //! \param nsamps is the length of the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param time is the time in seconds at which to attempt to estimate - //! the fundamental frequency - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \return the estimate of fundamental frequency in Hz and the - //! confidence associated with that estimate (see - //! F0Estimate.h) - - value_type estimateAt( const double * sampsBeg, - unsigned long nsamps, - double sampleRate, - double time, - double lowerFreqBound, double upperFreqBound ) - { - return estimateAt( sampsBeg, sampsBeg + nsamps, sampleRate, - time, lowerFreqBound, upperFreqBound ); - } - - // estimateAt - // - //! Return an estimate of the fundamental frequency computed - //! at the specified time. The F0Estimate returned stores the - //! estimate of the fundamental frequency (in Hz) and the - //! relative confidence (from 0 to 1) associated with that - //! estimate. - //! - //! \param samps is the sequence of samples - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param time is the time in seconds at which to attempt to estimate - //! the fundamental frequency - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \return the estimate of fundamental frequency in Hz and the - //! confidence associated with that estimate (see - //! F0Estimate.h) - - value_type estimateAt( const std::vector< double > & samps, - double sampleRate, - double time, - double lowerFreqBound, double upperFreqBound ) - { - return estimateAt( &samps[0], &samps[0] + samps.size(), sampleRate, - time, lowerFreqBound, upperFreqBound ); - } - - - -// -- spectral analysis parameter access/mutation -- - - //! Return the frequency-domain main lobe width (in Hz measured - //! between zero-crossings) of the analysis window used in spectral - //! analysis. - double windowWidth( void ) const; - - //! Set the frequency-domain main lobe width (in Hz measured - //! between zero-crossings) of the analysis window used in spectral - //! analysis. - //! - //! \param w is the new main lobe width in Hz - void setWindowWidth( double w ); - - - -// -- private auxiliary functions -- - -private: - - // buildSpectrumAnalyzer - // - //! Construct the ReassignedSpectrum that will be used to perform - //! spectral analysis from which peak frequencies and amplitudes - //! will be drawn. This construction is performed in a lazy fashion, - //! and needs to be done again when certain of the parameters change. - //! - //! \param srate is the sampling frequency in Hz, needed to compute - //! analysis window parameters - void buildSpectrumAnalyzer( double srate ); - - - // collectFreqsAndAmps - // - //! Perform spectral analysis on a sequence of samples, using - //! an analysis window centered at the specified time in seconds. - //! Collect the frequencies and amplitudes of the peaks and return - //! them in the vectors provided. - //! - //! \param samps is the beginning of a sequence of samples - //! \param nsamps is the length of the sequence of Partials - //! \param sampleRate is the sampling rate (in Hz) associated - //! with the sequence of samples (used to compute frequencies - //! in Hz, and to convert the time from seconds to samples) - //! \param frequencies is a vector in which to store a sequence of - //! frequencies to be used to estimate the most likely - //! fundamental frequency - //! \param amplitudes is a vector in which to store a sequence of - //! amplitudes to be used to estimate the most likely - //! fundamental frequency - //! \param time is the time in seconds at which to collect frequencies - //! and amplitudes of spectral peaks - - void collectFreqsAndAmps( const double * samps, - unsigned long nsamps, - double sampleRate, - std::vector< double > & frequencies, - std::vector< double > & amplitudes, - double time ); - - -// -- private member variables -- - - std::auto_ptr< ReassignedSpectrum > m_spectrum; - //! the spectrum analyzer - - double m_cacheSampleRate; //! the sample rate used to construct the - - double m_windowWidth; //! the width of the main lobe of the window to - //! be used in spectral analysis, in Hz - -// disallow these until they are implemented - - FundamentalFromSamples( const FundamentalFromSamples & ); - FundamentalFromSamples & operator= ( const FundamentalFromSamples & ); - -}; // end of class FundamentalFromSamples - - - -// --------------------------------------------------------------------------- -// class FundamentalFromPartials -// -//! Class FundamentalFromPartials represents an algorithm for -//! time-varying fundamental frequency estimation from instantaneous -//! Partial amplitudes and frequencies based on a likelihood -//! estimator adapted from Quatieri's Speech Signal Processing text - -class FundamentalFromPartials : public FundamentalEstimator -{ -// -- public interface -- - -public: - -// -- lifecycle -- - - //! Construct a new estimator. - //! - //! The specified precision is used to terminate the iterative - //! estimation procedure. If unspecified, the default value, - //! DefaultPrecisionOver100 * 100 is used. - //! - //! \param precisionHz is the precision in Hz with which the - //! fundamental estimates will be made. - FundamentalFromPartials( double precisionHz = DefaultPrecisionOver100 * 0.01 ); - - - //! Destructor - ~FundamentalFromPartials( void ); - - //! Construct a copy of an estimator. Nothing much to do since this class - //! has no data members. - FundamentalFromPartials( const FundamentalFromPartials & ); - - //! Pass the assignment opertion up to the base class. - FundamentalFromPartials & operator= ( const FundamentalFromPartials & ); - -// -- fundamental frequency estimation -- - - // buildEnvelope - // - //! Construct a linear envelope from fundamental frequency - //! estimates taken at the specified interval in seconds - //! starting at tbeg (seconds) and ending before tend (seconds). - //! - //! \param begin_partials is the beginning of a sequence of Partials - //! \param end_partials is the end of a sequence of Partials - //! \param tbeg is the beginning of the time interval (in seconds) - //! \param tend is the end of the time interval (in seconds) - //! \param interval is the time between breakpoints in the - //! fundamental frequency envelope (in seconds) - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param confidenceThreshold is the minimum confidence level - //! resuired for a fundamental frequency estimate to be - //! added to the envelope. Lower confidence estimates are - //! not added, the envelope returned will not contain - //! breakpoints at times associated with low confidence - //! estimates - //! \return a LinearEnvelope composed of breakpoints corresponding to - //! the fundamental frequency estimates at samples of the span - //! tbeg to tend at the specified sampling interval, only estimates - //! having confidence level exceeding the specified confidence - //! threshold are added to the envelope - LinearEnvelope buildEnvelope( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ); - - // buildEnvelope - // - //! Construct a linear envelope from fundamental frequency - //! estimates taken at the specified interval in seconds - //! starting at tbeg (seconds) and ending before tend (seconds). - //! - //! \param partials is the sequence of Partials - //! \param tbeg is the beginning of the time interval (in seconds) - //! \param tend is the end of the time interval (in seconds) - //! \param interval is the time between breakpoints in the - //! fundamental frequency envelope (in seconds) - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param confidenceThreshold is the minimum confidence level - //! resuired for a fundamental frequency estimate to be - //! added to the envelope. Lower confidence estimates are - //! not added, the envelope returned will not contain - //! breakpoints at times associated with low confidence - //! estimates - //! \return a LinearEnvelope composed of breakpoints corresponding to - //! the fundamental frequency estimates at samples of the span - //! tbeg to tend at the specified sampling interval, only estimates - //! having confidence level exceeding the specified confidence - //! threshold are added to the envelope - LinearEnvelope buildEnvelope( const PartialList & partials, - double tbeg, double tend, - double interval, - double lowerFreqBound, double upperFreqBound, - double confidenceThreshold ) - { - return buildEnvelope( partials.begin(), partials.end(), - tbeg, tend, interval, - lowerFreqBound, upperFreqBound, - confidenceThreshold ); - } - - - // estimateAt - // - //! Return an estimate of the fundamental frequency computed - //! at the specified time. The F0Estimate returned stores the - //! estimate of the fundamental frequency (in Hz) and the - //! relative confidence (from 0 to 1) associated with that - //! estimate. - //! - //! \param begin_partials is the beginning of a sequence of Partials - //! \param end_partials is the end of a sequence of Partials - //! \param time is the time in seconds at which to attempt to estimate - //! the fundamental frequency - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \return the estimate of fundamental frequency in Hz and the - //! confidence associated with that estimate (see - //! F0Estimate.h) - value_type estimateAt( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double time, - double lowerFreqBound, double upperFreqBound ); - - // estimateAt - // - //! Return an estimate of the fundamental frequency computed - //! at the specified time. The F0Estimate returned stores the - //! estimate of the fundamental frequency (in Hz) and the - //! relative confidence (from 0 to 1) associated with that - //! estimate. - //! - //! \param partials is the sequence of Partials - //! \param time is the time in seconds at which to attempt to estimate - //! the fundamental frequency - //! \param lowerFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \param upperFreqBound is the lower bound on the fundamental - //! frequency estimate (in Hz) - //! \return the estimate of fundamental frequency in Hz and the - //! confidence associated with that estimate (see - //! F0Estimate.h) - value_type estimateAt( const PartialList & partials, - double time, - double lowerFreqBound, double upperFreqBound ) - { - return estimateAt( partials.begin(), partials.end(), - time, - lowerFreqBound, upperFreqBound ); - } - - hise::ThreadController* controller = nullptr; - -// -- private auxiliary functions -- - -private: - - // collectFreqsAndAmps - // - //! Collect the frequencies and amplitudes of a range of partials - //! at the specified time and return them in the vectors provided. - //! - //! \param begin_partials is the beginning of a sequence of Partials - //! \param end_partials is the end of a sequence of Partials - //! \param frequencies is a vector in which to store a sequence of - //! frequencies to be used to estimate the most likely - //! fundamental frequency - //! \param amplitudes is a vector in which to store a sequence of - //! amplitudes to be used to estimate the most likely - //! fundamental frequency - //! \param time is the time in seconds at which to collect frequencies - //! and amplitudes of the Partials - void collectFreqsAndAmps( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - std::vector< double > & frequencies, - std::vector< double > & amplitudes, - double time ); - - - -}; // end of class FundamentalFromPartials - - - -} // end of namespace Loris - -#endif // ndef INCLUDE_FUNDAMENTAL_H diff --git a/loris_library/Source/src/Harmonifier.cpp b/loris_library/Source/src/Harmonifier.cpp deleted file mode 100644 index 3a41c58..0000000 --- a/loris_library/Source/src/Harmonifier.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Harmonifier.h - * - * Definition of class Harmonifier. - * - * Kelly Fitz, 26 Oct 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "Harmonifier.h" - -#include "LinearEnvelope.h" - -#include // for pow - -using namespace Loris; - - -// --------------------------------------------------------------------------- -// Constructor -// --------------------------------------------------------------------------- -//! Construct a new Harmonifier that applies the specified -//! reference Partial to fix the frequencies of Breakpoints -//! whose amplitude is below threshold_dB (0 by default, -//! to apply only to quiet Partials, specify a threshold, -//! like -90). -// -Harmonifier::Harmonifier( const Partial & ref, double threshold_dB ) : - _refPartial( ref ), - _freqFixThresholdDb( threshold_dB ), - _weight( createDefaultEnvelope() ) -{ - if ( 0 == _refPartial.numBreakpoints() ) - { - Throw( InvalidArgument, - "Cannot use an empty reference Partial in Harmonizer" ); - } - if ( 0 == _refPartial.label() ) - { - // if the reference is unlabeled, assume that it is the fundamental - _refPartial.setLabel( 1 ); - } - -} - -// --------------------------------------------------------------------------- -// Constructor -// --------------------------------------------------------------------------- -//! Construct a new Harmonifier that applies the specified -//! reference Partial to fix the frequencies of Breakpoints -//! whose amplitude is below threshold_dB (0 by default, -//! to apply only to quiet Partials, specify a threshold, -//! like -90). The Envelope is a time-varying weighting -//! on the harmonifing process. When 1, harmonic frequencies -//! are used, when 0, breakpoint frequencies are unmodified. -// -Harmonifier::Harmonifier( const Partial & ref, const Envelope & env, - double threshold_dB ) : - _refPartial( ref ), - _freqFixThresholdDb( threshold_dB ), - _weight( env.clone() ) -{ - if ( 0 == _refPartial.numBreakpoints() ) - { - Throw( InvalidArgument, - "Cannot use an empty reference Partial in Harmonizer" ); - } - if ( 0 == _refPartial.label() ) - { - // if the reference is unlabeled, assume that it is the fundamental - _refPartial.setLabel( 1 ); - } - -} - -// --------------------------------------------------------------------------- -// Destructor -// --------------------------------------------------------------------------- -Harmonifier::~Harmonifier( void ) -{ -} - -// --------------------------------------------------------------------------- -// harmonify -// --------------------------------------------------------------------------- -//! Apply the reference envelope to a Partial. -//! -//! \pre The Partial p must be labeled with its harmonic number. -// -void Harmonifier::harmonify( Partial & p ) const -{ - // compute absolute magnitude thresholds: - static const double FadeRangeDB = 10; - const double BeginFade = std::pow( 10., 0.05 * (_freqFixThresholdDb+FadeRangeDB) ); - const double Threshold = std::pow( 10., 0.05 * _freqFixThresholdDb ); - const double OneOverFadeSpan = 1. / ( BeginFade - Threshold ); - - double fscale = (double)p.label() / _refPartial.label(); - - for ( Partial::iterator it = p.begin(); it != p.end(); ++it ) - { - Breakpoint & bp = it.breakpoint(); - - if ( bp.amplitude() < BeginFade ) - { - // alpha is the harmonic frequency weighting: - // when alpha is 1, the harmonic frequency is used, - // when alpha is 0, the breakpoint frequency is - // unmodified. - double alpha = - std::min( ( BeginFade - bp.amplitude() ) * OneOverFadeSpan, 1. ); - - // alpha is scaled by the weigthing envelope - alpha *= _weight->valueAt( it.time() ); - - double fRef = _refPartial.frequencyAt( it.time() ); - - bp.setFrequency( ( alpha * ( fRef * fscale ) ) + - ( (1 - alpha) * bp.frequency() ) ); - } - - } -} - -// --------------------------------------------------------------------------- -// createDefaultEnvelope (STATIC) -// --------------------------------------------------------------------------- -//! Return the default weighing envelope (always 1). -//! Used in template constructors. -// -Envelope * Harmonifier::createDefaultEnvelope( void ) -{ - return new LinearEnvelope( 1 ); -} - diff --git a/loris_library/Source/src/Harmonifier.h b/loris_library/Source/src/Harmonifier.h deleted file mode 100644 index b1b04d8..0000000 --- a/loris_library/Source/src/Harmonifier.h +++ /dev/null @@ -1,441 +0,0 @@ -#ifndef INCLUDE_HARMONIFIER_H -#define INCLUDE_HARMONIFIER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Harmonifier.h - * - * Definition of class Harmonifier. - * - * Kelly Fitz, 26 Oct 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "Envelope.h" -#include "LorisExceptions.h" -#include "Partial.h" -#include "PartialUtils.h" - -#include // for find -#include // for auto_ptr - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// Class Harmonifier -// -//! A Harmonifier uses a reference frequency envelope to make the -//! frequencies of labeled Partials harmonic. The amount of frequency -//! adjustment can be controlled by a time-varying envelope, and a -//! threshold can be supplied so that only quiet Partials are affected. -// -class Harmonifier -{ -// -- instance variables -- - - Partial _refPartial; //! the Partial whose frequency supplies the - //! reference frequency envelope. - - double _freqFixThresholdDb; //! amplitude threshold below which Partial - //! frequencies are corrected according to - //! a reference Partial, if specified. - - std::auto_ptr< Envelope > _weight; //! weighting function, when 1 harmonic - //! frequencies are used, when 0 breakpoint - //! frequencies are unmodified. - -// -- public interface -- -public: - -// -- lifecycle -- - - //! Construct a new Harmonifier that applies the specified - //! reference Partial to fix the frequencies of Breakpoints - //! whose amplitude is below threshold_dB (0 by default, - //! to apply only to quiet Partials, specify a threshold, - //! like -90). - Harmonifier( const Partial & ref, double threshold_dB = 0 ); - - //! Construct a new Harmonifier that applies the specified - //! reference Partial to fix the frequencies of Breakpoints - //! whose amplitude is below threshold_dB (0 by default, - //! to apply only to quiet Partials, specify a threshold, - //! like -90). The Envelope is a time-varying weighting - //! on the harmonifing process. When 1, harmonic frequencies - //! are used, when 0, breakpoint frequencies are unmodified. - Harmonifier( const Partial & ref, const Envelope & env, - double threshold_dB = 0 ); - - //! Construct a new Harmonifier that applies the specified - //! reference Partial to fix the frequencies of Breakpoints - //! whose amplitude is below threshold_dB (0 by default, - //! to apply only to quiet Partials, specify a threshold, - //! like -90). The reference Partial is the first Partial - //! in the range [b,e) having the specified label. - // - //! \throw InvalidArgument if no Partial in the range [b,e) - //! has the specified label. - // -#if ! defined(NO_TEMPLATE_MEMBERS) - template - Harmonifier( Iter b, Iter e, Partial::label_type refLabel, - double threshold_dB = 0 ); -#else - inline - Harmonifier( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, double threshold_dB = 0 ); -#endif - - //! Construct a new Harmonifier that applies the specified - //! reference Partial to fix the frequencies of Breakpoints - //! whose amplitude is below threshold_dB (0 by default, - //! to apply only to quiet Partials, specify a threshold, - //! like -90). The reference Partial is the first Partial - //! in the range [b,e) having the specified label. - //! - //! The Envelope is a time-varying weighting - //! on the harmonifing process. When 1, harmonic frequencies - //! are used, when 0, breakpoint frequencies are unmodified. - // - //! \throw InvalidArgument if no Partial in the range [b,e) - //! has the specified label. - // -#if ! defined(NO_TEMPLATE_MEMBERS) - template - Harmonifier( Iter b, Iter e, Partial::label_type refLabel, - const Envelope & env, double threshold_dB = 0 ); -#else - inline - Harmonifier( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, const Envelope & env, - double threshold_dB = 0 ); -#endif - - //! Destructor. - ~Harmonifier( void ); - - // use compiler-generated copy and assign. - -// -- operation -- - - //! Apply the reference envelope to a Partial. - void harmonify( Partial & p ) const; - - //! Apply the reference envelope to all Partials in a range. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void harmonify( Iter b, Iter e ); -#else - inline - void harmonify( PartialList::iterator b, PartialList::iterator e ); -#endif - -// -- static members -- - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Harmonifier using as reference the Partial in - //! the specified range labeled refLabel, then apply - //! the instance to all Partials in the range. - //! - //! \param b is the beginning of the range of Partials to harmonify - //! \param e is (one-past) the end of the range of Partials to harmonify - //! \param refLabel is the label of the Partial in [b,e) to - //! use as reference Partial. The reference Partial is the first - //! Partial in the range [b,e) having the specified label. - //! \param threshold_dB is the amplitude below which breakpoint - //! frequencies are harmonified (0 by default, to apply - //! only to quiet Partials, specify a threshold, like -90). - //! - //! \throw InvalidArgument if no Partial in the range [b,e) - //! has the specified label. - //! \throw InvalidArgument if refLabel is non-positive. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - static - void harmonify( Iter b, Iter e, - Partial::label_type refLabel, - double threshold_dB = 0 ); -#else - static inline - void harmonify( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, - double threshold_dB = 0 ); -#endif - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Harmonifier using as reference the Partial in - //! the specified range labeled refLabel, then apply - //! the instance to all Partials in the range. - //! - //! \param b is the beginning of the range of Partials to harmonify - //! \param e is (one-past) the end of the range of Partials to harmonify - //! \param refLabel is the label of the Partial in [b,e) to - //! use as reference Partial. The reference Partial is the first - //! Partial in the range [b,e) having the specified label. - //! \param env is a weighting envelope to apply to the harmonification - //! process: when env is 1, use harmonic frequencies, when env - //! is 0, breakpoint frequencies are unmodified. - //! \param threshold_dB is the amplitude below which breakpoint - //! frequencies are harmonified (0 by default, to apply - //! only to quiet Partials, specify a threshold, like -90). - //! - //! \throw InvalidArgument if no Partial in the range [b,e) - //! has the specified label. - //! \throw InvalidArgument if refLabel is non-positive. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - static - void harmonify( Iter b, Iter e, - Partial::label_type refLabel, - const Envelope & env, double threshold_dB = 0 ); -#else - static inline - void harmonify( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, - const Envelope & env, double threshold_dB = 0 ); -#endif - -private: - -// -- helpers -- - - //! Return the default weighing envelope (always 1). - //! Used in template constructors. - static Envelope * createDefaultEnvelope( void ); - -}; - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Construct a new Harmonifier that applies the specified -//! reference Partial to fix the frequencies of Breakpoints -//! whose amplitude is below threshold_dB (0 by default, -//! to apply only to quiet Partials, specify a threshold, -//! like -90). The reference Partial is the first Partial -//! in the range [b,e) having the specified label. -//! \throw InvalidArgument if no Partial in the range [b,e) -//! has the specified label. -//! \throw InvalidArgument if refLabel is non-positive. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -Harmonifier::Harmonifier( Iter b, Iter e, Partial::label_type refLabel, - double threshold_dB ) : -#else -inline -Harmonifier::Harmonifier( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, double threshold_dB ) : -#endif - _freqFixThresholdDb( threshold_dB ), - _weight( createDefaultEnvelope() ) -{ - if ( 1 > refLabel ) - { - Throw( InvalidArgument, "The reference label must be positive." ); - } - - b = std::find_if( b, e, PartialUtils::isLabelEqual( refLabel ) ); - if ( b == e ) - { - Throw( InvalidArgument, "no Partial has the specified reference label" ); - } - - if ( 0 == b->numBreakpoints() ) - { - Throw( InvalidArgument, - "Cannot use an empty reference Partial in Harmonizer" ); - } - _refPartial = *b; -} - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Construct a new Harmonifier that applies the specified -//! reference Partial to fix the frequencies of Breakpoints -//! whose amplitude is below threshold_dB (0 by default, -//! to apply only to quiet Partials, specify a threshold, -//! like -90). The reference Partial is the first Partial -//! in the range [b,e) having the specified label. -//! -//! The Envelope is a time-varying weighting -//! on the harmonifing process. When 1, harmonic frequencies -//! are used, when 0, breakpoint frequencies are unmodified. -//! -//! \throw InvalidArgument if no Partial in the range [b,e) -//! has the specified label. -//! \throw InvalidArgument if refLabel is non-positive. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -Harmonifier::Harmonifier( Iter b, Iter e, Partial::label_type refLabel, - const Envelope & env, double threshold_dB ) : -#else -inline -Harmonifier::Harmonifier( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, const Envelope & env, - double threshold_dB ) : -#endif - _freqFixThresholdDb( threshold_dB ), - _weight( env.clone() ) -{ - if ( 1 > refLabel ) - { - Throw( InvalidArgument, "The reference label must be positive." ); - } - - b = std::find_if( b, e, PartialUtils::isLabelEqual( refLabel ) ); - if ( b == e ) - { - Throw( InvalidArgument, "no Partial has the specified reference label" ); - } - - if ( 0 == b->numBreakpoints() ) - { - Throw( InvalidArgument, - "Cannot use an empty reference Partial in Harmonizer" ); - } - _refPartial = *b; -} - -// --------------------------------------------------------------------------- -// harmonify -// --------------------------------------------------------------------------- -//! Apply the reference envelope to all Partials in a range. -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Harmonifier::harmonify( Iter b, Iter e ) -#else -inline -void Harmonifier::harmonify( PartialList::iterator b, PartialList::iterator e ) -#endif -{ - while ( b != e ) - { - harmonify( *b ); - ++b; - } -} - -// --------------------------------------------------------------------------- -// harmonify (STATIC) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! Construct a Harmonifier using as reference the Partial in -//! the specified range labeled refLabel, then apply -//! the instance to all Partials in the range. -//! -//! \param b is the beginning of the range of Partials to harmonify -//! \param e is (one-past) the end of the range of Partials to harmonify -//! \param refLabel is the label of the Partial in [b,e) to -//! use as reference Partial. The reference Partial is the first -//! Partial in the range [b,e) having the specified label. -//! \param threshold_dB is the amplitude below which breakpoint -//! frequencies are harmonified (0 by default, to apply -//! only to quiet Partials, specify a threshold, like -90). -//! -//! \throw InvalidArgument if no Partial in the range [b,e) -//! has the specified label. -//! \throw InvalidArgument if refLabel is non-positive. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Harmonifier::harmonify( Iter b, Iter e, - Partial::label_type refLabel, - double threshold_dB ) -#else -inline -void Harmonifier::harmonify( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, - double threshold_dB ) -#endif -{ - Harmonifier instance( b, e, refLabel, threshold_dB ); - instance.harmonify( b, e ); -} - -// --------------------------------------------------------------------------- -// harmonify (STATIC) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! Construct a Harmonifier using as reference the Partial in -//! the specified range labeled refLabel, then apply -//! the instance to all Partials in the range. -//! -//! \param b is the beginning of the range of Partials to harmonify -//! \param e is (one-past) the end of the range of Partials to harmonify -//! \param refLabel is the label of the Partial in [b,e) to -//! use as reference Partial. The reference Partial is the first -//! Partial in the range [b,e) having the specified label. -//! \param env is a weighting envelope to apply to the harmonification -//! process: when env is 1, use harmonic frequencies, when env -//! is 0, breakpoint frequencies are unmodified. -//! \param threshold_dB is the amplitude below which breakpoint -//! frequencies are harmonified (0 by default, to apply -//! only to quiet Partials, specify a threshold, like -90). -//! -//! \throw InvalidArgument if no Partial in the range [b,e) -//! has the specified label. -//! \throw InvalidArgument if refLabel is non-positive. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Harmonifier::harmonify( Iter b, Iter e, - Partial::label_type refLabel, - const Envelope & env, double threshold_dB ) -#else -inline -void Harmonifier::harmonify( PartialList::iterator b, PartialList::iterator e, - Partial::label_type refLabel, - const Envelope & env, double threshold_dB ) -#endif -{ - Harmonifier instance( b, e, refLabel, env, threshold_dB ); - instance.harmonify( b, e ); -} - -} // namespace Loris - -#endif /* ndef INCLUDE_HARMONIFIER_H */ diff --git a/loris_library/Source/src/ImportLemur.cpp b/loris_library/Source/src/ImportLemur.cpp deleted file mode 100644 index f14dc4b..0000000 --- a/loris_library/Source/src/ImportLemur.cpp +++ /dev/null @@ -1,519 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * ImportLemur.C - * - * Implementation of class Loris::ImportLemur for importing Partials stored - * in Lemur 5 alpha files. - * - * Kelly Fitz, 10 Sept 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "ImportLemur.h" -#include "BigEndian.h" -#include "LorisExceptions.h" -#include "Partial.h" -#include "PartialList.h" -#include "Breakpoint.h" -#include "Notifier.h" -#include -#include -#include -#include - -// in case configure wasn't run (no config.h), -// pick some (hopefully-) reasonable values for -// these things and hope for the best... -#if ! defined( SIZEOF_SHORT ) -#define SIZEOF_SHORT 2 -#endif - -#if ! defined( SIZEOF_INT ) -#define SIZEOF_INT 4 -#endif - -#if ! defined( SIZEOF_LONG ) -#define SIZEOF_LONG 4 // not for DEC Alpha! -#endif - -#if SIZEOF_SHORT == 2 -typedef short Int_16; -typedef unsigned short Uint_16; -#elif SIZEOF_INT == 2 -typedef int Int_16; -typedef unsigned int Uint_16; -#else -#error "cannot find an appropriate type for 16-bit integers" -#endif - -#if SIZEOF_INT == 4 -typedef int Int_32; -typedef unsigned int Uint_32; -#elif SIZEOF_LONG == 4 -typedef long Int_32; -typedef unsigned long Uint_32; -#else -#error "cannot find an appropriate type for 32-bit integers" -#endif - - -#if ! defined( SIZEOF_FLOAT ) || SIZEOF_FLOAT == 4 -typedef float Float_32; -#else -#error "cannot find an appropriate type for 32-bit floats" -#endif - -#if ! defined( SIZEOF_DOUBLE ) || SIZEOF_DOUBLE == 8 -typedef double Double_64; -#else -#error "cannot find an appropriate type for 64-bit double-precision floats" -#endif - - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -// begin namespace -namespace Loris { - -// -- types and ids -- -enum { - ContainerId = 0x464f524d, // 'FORM' - LEMR_ID = 0x4c454d52, // 'LEMR' - AnalysisParamsID = 0x4c4d414e, // 'LMAN' - TrackDataID = 0x54524b53, // 'TRKS' - FormatNumber = 4962 }; - -// for reading and writing files, the exact sizes and -// alignments are critical. -typedef Int_32 ID; -struct CkHeader -{ - Int_32 id; - Int_32 size; -}; - -struct ContainerCk -{ - CkHeader header; - ID formType; -}; - -struct AnalysisParamsCk -{ - //Int_32 ckID; - //Int_32 ckSize; - CkHeader header; - - Int_32 formatNumber; - Int_32 originalFormatNumber; - - Int_32 ftLength; // samples, transform length - Float_32 winWidth; // Hz, main lobe width - Float_32 winAtten; // dB, sidelobe attenuation - Int_32 hopSize; // samples, frame length - Float_32 sampleRate; // Hz, from analyzed sample - - Float_32 noiseFloor; // dB (negative) - Float_32 peakAmpRange; // dB, floating relative amplitde threshold - Float_32 maskingRolloff; // dB/Hz, peak masking curve - Float_32 peakSeparation; // Hz, minimum separation between peaks - Float_32 freqDrift; // Hz, maximum track freq drift over a frame -}; - -struct TrackDataCk -{ - CkHeader header; - Uint_32 numberOfTracks; - Int_32 trackOrder; // enumerated type - // track data follows -}; - -struct TrackOnDisk -{ - Double_64 startTime; // in milliseconds - Float_32 initialPhase; - Uint_32 numPeaks; - Int_32 label; -}; - -struct PeakOnDisk -{ - Float_32 magnitude; - Float_32 frequency; - Float_32 interpolatedFrequency; - Float_32 bandwidth; - Double_64 ttn; -}; - -// prototypes for import helpers: -static void importPartials( std::istream & s, PartialList & partials, double bweCutoff ); -static void getPartial( std::istream & s, PartialList & partials, double bweCutoff ); -static void readChunkHeader( std::istream & s, CkHeader & ck ); -static void readContainer( std::istream & s ); -static void readParamsChunk( std::istream & s ); -static long readTracksChunk( std::istream & s ); -static void readTrackHeader( std::istream & s, TrackOnDisk & t ); -static void readPeakData( std::istream & s, PeakOnDisk & p ); - -// --------------------------------------------------------------------------- -// ImportLemur constructor -// --------------------------------------------------------------------------- -// Imports immediately. -// bweCutoff defaults to 1kHz, the default cutoff in Lemur. -// Clients should be prepared to catch ImportErrors. -// -ImportLemur::ImportLemur( const std::string & fname, double bweCutoff /* = 1000 Hz */) -{ - std::fstream fs; - try - { - fs.open( fname.c_str(), std::ios::in | std::ios::binary ); - } - catch( std::exception & ex ) - { - Throw( ImportException, ex.what() ); - } - importPartials( fs, _partials, bweCutoff ); -} - -// --------------------------------------------------------------------------- -// importPartials -// --------------------------------------------------------------------------- -// Clients should be prepared to catch ImportExceptions. -// -// THIS WON'T WORK IF CHUNKS ARE IN A DIFFERENT ORDER!!! -// Fortunately, they never will be, since only the research -// version of Lemur ever wrote these files anyway. -// -static void -importPartials( std::istream & s, PartialList & partials, double bweCutoff ) -{ - try - { - // the Container chunk must be first, read it: - readContainer( s ); - - // read other chunks: - bool foundParams = false, foundTracks = false; - while ( ! foundParams || ! foundTracks ) - { - // read a chunk header, if it isn't the one we want, skip over it. - CkHeader h; - readChunkHeader( s, h ); - - if ( h.id == AnalysisParamsID ) - { - readParamsChunk( s ); - foundParams = true; - } - else if ( h.id == TrackDataID ) - { - if (! foundParams) // I hope this doesn't happen - { - Throw( ImportException, - "Mia culpa! I am not smart enough to read the Track data before the Analysis Parameters data." ); - } - // read Partials: - for ( long counter = readTracksChunk( s ); counter > 0; --counter ) - { - getPartial(s, partials, bweCutoff); - } - foundTracks = true; - } - else - { - s.ignore( h.size ); - } - } - - } - catch ( Exception & ex ) - { - if ( s.eof() ) - { - ex.append("Reached end of file before finding both a Tracks chunk and a Parameters chunk."); - } - ex.append( "Import failed." ); - Throw( ImportException, ex.str() ); - } - -} - -// --------------------------------------------------------------------------- -// readContainer -// --------------------------------------------------------------------------- -// -static void -readContainer( std::istream & s ) -{ - ContainerCk ck; - try - { - // read chunk header: - readChunkHeader( s, ck.header ); - if( ck.header.id != ContainerId ) - Throw( FileIOException, "Found no Container chunk." ); - - // read FORM type - BigEndian::read( s, 1, sizeof(ID), (char *)&ck.formType ); - } - catch( FileIOException & ex ) - { - ex.append( "Failed to read badly-formatted Lemur file (bad Container chunk)." ); - throw; - } - - // make sure its really a Dr. Lemur file: - if ( ck.formType != LEMR_ID ) - { - Throw( ImportException, "File is not formatted correctly for Lemur 5 import." ); - } -} - -// --------------------------------------------------------------------------- -// getPartial -// --------------------------------------------------------------------------- -// Convert any FileIOExceptions into ImportExceptions, so that clients can -// reasonably expect to catch only ImportExceptions. -// -static void -getPartial( std::istream & s, PartialList & partials, double bweCutoff ) -{ - try - { - // read the Track header: - TrackOnDisk tkHeader; - readTrackHeader( s, tkHeader ); - - // create a Partial: - Partial p; - p.setLabel( tkHeader.label ); - - // keep running phase and time for Breakpoint construction: - double phase = tkHeader.initialPhase; - - // convert time to seconds and offset by a millisecond to - // allow for implied onset (Lemur analysis data was shifted - // such that the earliest Partial starts at 0). - double time = tkHeader.startTime * 0.001; - - // use this to compute phases: - double prevTtnSec = 0.; - - // loop: read Peak, create Breakpoint, add to Partial: - for ( int i = 0; i < tkHeader.numPeaks; ++i ) { - // read Peak: - PeakOnDisk pkData; - readPeakData( s, pkData ); - - double frequency = pkData.frequency; - double amplitude = pkData.magnitude; - double bandwidth = std::min( pkData.bandwidth, 1.f ); - - // fix bandwidth: - // Lemur used a cutoff frequency, below which - // bandwidth was ignored; Loris does not, so - // toss out that bogus bandwidth. - if ( frequency < bweCutoff ) { - amplitude *= std::sqrt(1. - bandwidth); - bandwidth = 0.; - } - // otherwise, adjust the bandwidth value - // to account for the difference in noise - // scaling between Lemur and Loris; this - // mess doubles the noise modulation index - // without changing the sine modulation index, - // see Oscillator::modulate(). - else { - amplitude *= std::sqrt( 1. + (3. * bandwidth) ); - bandwidth = (4. * bandwidth) / ( 1. + (3. * bandwidth) ); - } - - // update phase based on _this_ pkData's interpolated freq: - phase +=2. * Pi * prevTtnSec * pkData.interpolatedFrequency; - phase = std::fmod( phase, 2. * Pi ); - - // create Breakpoint: - Breakpoint bp( frequency, amplitude, bandwidth, phase ); - - // insert in Partial: - p.insert( time, bp ); - - // update time: - prevTtnSec = pkData.ttn * 0.001; - time += prevTtnSec; - } - - if ( p.duration() > 0. ) { - partials.push_back( p ); - } - /* - else { - debugger << "import rejecting a Partial of zero duration (" - << tkHeader.numPeaks << " peaks read)" << endl; - } - */ - } - catch( FileIOException & ex ) { - ex.append( "Failed to import a partial from a Lemur file." ); - throw; - } - -} - -// --------------------------------------------------------------------------- -// readChunkHeader -// --------------------------------------------------------------------------- -// Read the id and chunk size from the current file position. -// -static void -readChunkHeader( std::istream & s, CkHeader & h ) -{ - BigEndian::read( s, 1, sizeof(ID), (char *)&h.id ); - BigEndian::read( s, 1, sizeof(Int_32), (char *)&h.size ); -} - -// --------------------------------------------------------------------------- -// readTracksChunk -// --------------------------------------------------------------------------- -// Leave file positioned at end of chunk header data and at the beginning -// of the first track. -// Assumes that the stream is correctly positioned and that the chunk -// header has been read. -// Returns the number of tracks to read. -// -static long -readTracksChunk( std::istream & s ) -{ - TrackDataCk ck; - try - { - // found it, read it one field at a time: - BigEndian::read( s, 1, sizeof(Uint_32), (char *)&ck.numberOfTracks ); - BigEndian::read( s, 1, sizeof(Int_32), (char *)&ck.trackOrder ); - } - catch( FileIOException & ex ) - { - ex.append( "Failed to read badly-formatted Lemur file (bad Track Data chunk)." ); - throw; - } - - return ck.numberOfTracks; -} - -// --------------------------------------------------------------------------- -// readParamsChunk -// --------------------------------------------------------------------------- -// Verify that the file has the correct format and is available for reading. -// Assumes that the stream is correctly positioned and that the chunk -// header has been read. -// -static void -readParamsChunk( std::istream & s ) -{ - AnalysisParamsCk ck; - try - { - BigEndian::read( s, 1, sizeof(Int_32), (char *)&ck.formatNumber ); - BigEndian::read( s, 1, sizeof(Int_32), (char *)&ck.originalFormatNumber ); - - BigEndian::read( s, 1, sizeof(Int_32), (char *)&ck.ftLength ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&ck.winWidth ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&ck.winAtten ); - BigEndian::read( s, 1, sizeof(Int_32), (char *)&ck.hopSize ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&ck.sampleRate ); - - BigEndian::read( s, 1, sizeof(Float_32), (char *)&ck.noiseFloor ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&ck.peakAmpRange ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&ck.maskingRolloff ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&ck.peakSeparation ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&ck.freqDrift ); - } - catch( FileIOException & ex ) - { - ex.append( "Failed to read badly-formatted Lemur file (bad Parameters chunk)." ); - throw; - } - - if ( ck.formatNumber != FormatNumber ) - { - Throw( FileIOException, "File has wrong Lemur format for Lemur 5 import." ); - } -} - -// --------------------------------------------------------------------------- -// readTrackHeader -// --------------------------------------------------------------------------- -// Read from current position. -// -static void -readTrackHeader( std::istream & s, TrackOnDisk & t ) -{ - try - { - BigEndian::read( s, 1, sizeof(Double_64), (char *)&t.startTime ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&t.initialPhase ); - BigEndian::read( s, 1, sizeof(Uint_32), (char *)&t.numPeaks ); - BigEndian::read( s, 1, sizeof(Int_32), (char *)&t.label ); - } - catch( FileIOException & ex ) - { - ex.append( "Failed to read track data in Lemur 5 import." ); - throw; - } -} - -// --------------------------------------------------------------------------- -// readPeakData -// --------------------------------------------------------------------------- -// Read from current position. -// -static void -readPeakData( std::istream & s, PeakOnDisk & p ) -{ - try - { - BigEndian::read( s, 1, sizeof(Float_32), (char *)&p.magnitude ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&p.frequency ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&p.interpolatedFrequency ); - BigEndian::read( s, 1, sizeof(Float_32), (char *)&p.bandwidth ); - BigEndian::read( s, 1, sizeof(Double_64), (char *)&p.ttn ); - } - catch( FileIOException & ex ) - { - ex.append( "Failed to read peak data in Lemur 5 import." ); - throw; - } -} -} // end of namespace Loris diff --git a/loris_library/Source/src/ImportLemur.h b/loris_library/Source/src/ImportLemur.h deleted file mode 100644 index e887e64..0000000 --- a/loris_library/Source/src/ImportLemur.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef INCLUDE_IMPORTLEMUR_H -#define INCLUDE_IMPORTLEMUR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * ImportLemur.h - * - * Definition of class Loris::ImportLemur for importing Partials stored - * in Lemur 5 alpha files. - * - * Kelly Fitz, 10 Sept 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "PartialList.h" -#include "LorisExceptions.h" -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class ImportLemur -// -class ImportLemur -{ -// -- instance variables -- - PartialList _partials; // collect Partials here - -// -- public interface -- -public: -// construction: -// (compiler can generate destructor) - ImportLemur( const std::string & fname, double bweCutoff = 1000 ); - -// PartialList access: - PartialList & partials( void ) { return _partials; } - const PartialList & partials( void ) const { return _partials; } - -// -- unimplemented -- -private: - ImportLemur( const ImportLemur & other ); - ImportLemur & operator = ( const ImportLemur & rhs ); - -}; // end of class ImportLemur - -// --------------------------------------------------------------------------- -// class ImportException -// -// Class of exceptions thrown when there is an error importing -// Partials. -// -class ImportException : public Exception -{ -public: - ImportException( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Import Error -- ").append( str ), where ) {} -}; - -} // end of namespace Loris - -#endif /* ndef INCLUDE_IMPORTLEMUR_H */ diff --git a/loris_library/Source/src/KaiserWindow.cpp b/loris_library/Source/src/KaiserWindow.cpp deleted file mode 100644 index c7f3952..0000000 --- a/loris_library/Source/src/KaiserWindow.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * KaiserWindow.C - * - * Implementation of class Loris::KaiserWindow. - * - * Kelly Fitz, 14 Dec 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "KaiserWindow.h" -#include "LorisExceptions.h" -#include - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -using namespace std; - -// begin namespace -namespace Loris { - -// prototypes for static helpers, defined below -static double zeroethOrderBessel( double x ); -static double firstOrderBessel( double x ); - -// --------------------------------------------------------------------------- -// buildWindow -// --------------------------------------------------------------------------- -//! Build a new Kaiser analysis window having the specified shaping -//! parameter. See Oppenheim and Schafer: "Digital Signal Processing" -//! (1975), p. 452 for further explanation of the Kaiser window. Also, -//! see Kaiser and Schafer, 1980. -//! -//! \param win is the vector that will store the window -//! samples. The number of samples computed will be -//! equal to the length of this vector. Any previous -//! contents will be overwritten. -//! \param shape is the Kaiser shaping parameter, controlling -//! the sidelobe rejection level. -// -void -KaiserWindow::buildWindow( vector< double > & win, double shape ) -{ - // Pre-compute the shared denominator in the Kaiser equation. - const double oneOverDenom = 1.0 / zeroethOrderBessel( shape ); - - const unsigned int N = win.size() - 1; - const double oneOverN = 1.0 / N; - - for ( unsigned int n = 0; n <= N; ++n ) - { - const double K = (2.0 * n * oneOverN) - 1.0; - const double arg = sqrt( 1.0 - (K * K) ); - - win[n] = zeroethOrderBessel( shape * arg ) * oneOverDenom; - } -} - -// --------------------------------------------------------------------------- -// createDerivativeWindow -// --------------------------------------------------------------------------- -//! Build a new time-derivative Kaiser analysis window having the -//! specified shaping parameter, for computing frequency reassignment. -//! The closed form for the time derivative can be obtained from the -//! property of modified Bessel functions that the derivative of the -//! zeroeth order function is equal to the first order function. -//! -//! \param win is the vector that will store the window -//! samples. The number of samples computed will be -//! equal to the length of this vector. Any previous -//! contents will be overwritten. -//! \param shape is the Kaiser shaping parameter, controlling -//! the sidelobe rejection level. -// -void -KaiserWindow::buildTimeDerivativeWindow( vector< double > & win, double shape ) -{ - // Pre-compute the common factor that does not depend on n. - const unsigned int N = win.size() - 1; - const double oneOverN = 1.0 / N; - - const double commonFac = - 2.0 * shape / (N * zeroethOrderBessel( shape ) ); - - // w'[0] = w'[N] = 0 - win[0] = win[N] = 0.0; - - for ( unsigned int n = 1; n < N; ++n ) - { - const double K = (2.0 * n * oneOverN) - 1.0; - const double arg = sqrt( 1.0 - (K * K) ); - - win[n] = commonFac * firstOrderBessel( shape * arg ) * K / arg; - } -} - - -// --------------------------------------------------------------------------- -// zeroethOrderBessel -// --------------------------------------------------------------------------- -// Compute the zeroeth order modified Bessel function of the first kind -// at x using the series expansion, used to compute the Kasier window -// function. -// -static double zeroethOrderBessel( double x ) -{ - const double eps = 0.000001; - - // initialize the series term for m=0 and the result - double besselValue = 0; - double term = 1; - double m = 0; - - // accumulate terms as long as they are significant - while(term > eps * besselValue) - { - besselValue += term; - - // update the term - ++m; - term *= (x*x) / (4*m*m); - } - - return besselValue; -} - -// --------------------------------------------------------------------------- -// firstOrderBessel -// --------------------------------------------------------------------------- -// Compute the first order modified Bessel function of the first kind -// at x using the series expansion, used to compute the time derivative -// of the Kasier window function for computing frequency reassignment. -// -static double firstOrderBessel( double x ) -{ - const double eps = 0.000001; - - // initialize the series term for m=0 and the result - double besselValue = 0; - double term = .5*x; - double m = 0; - - // accumulate terms as long as they are significant - while(term > eps * besselValue) - { - besselValue += term; - - // update the term - ++m; - term *= (x*x) / (4*m*(m+1)); - } - - return besselValue; -} - -// --------------------------------------------------------------------------- -// computeShape -// --------------------------------------------------------------------------- -// Compute the Kaiser window shaping parameter from the specified attenuation -// of side lobes. This algorithm is given in Kaiser an Schafer,1980 and is -// supposed to give better than 0.36% accuracy (Kaiser and Schafer 1980). -// -double -KaiserWindow::computeShape( double atten ) -{ - if ( atten < 0. ) - { - Throw( InvalidArgument, - "Kaiser window shape must be computed from positive (> 0dB)" - " sidelobe attenuation. (received attenuation < 0)" ); - } - - double alpha; - - if ( atten > 60.0 ) - { - alpha = 0.12438 * (atten + 6.3); - } - else if ( atten > 13.26 ) - { - alpha = 0.76609L * ( pow((atten - 13.26), 0.4) ) + - 0.09834L * (atten - 13.26L); - } - else - { - // can't have less than 13dB. - alpha = 0.0; - } - - return alpha; -} -// --------------------------------------------------------------------------- -// computeLength -// --------------------------------------------------------------------------- -// Compute the length (in samples) of the Kaiser window from the desired -// (approximate) main lobe width and the control parameter. Of course, since -// the window must be an integer number of samples in length, your actual -// lobal mileage may vary. This equation appears in Kaiser and Schafer 1980 -// (on the use of the I0 window class for spectral analysis) as Equation 9. -// -// The main width of the main lobe must be normalized by the sample rate, -// that is, it is a fraction of the sample rate. -// -unsigned long -KaiserWindow::computeLength( double width, double alpha ) -{ - //double alpha = computeShape( atten ); - - // The last 0.5 is cheap rounding. - // But I think I don't need cheap rounding because the equation - // from Kaiser and Schafer has a +1 that appears to be a cheap - // ceiling function. - return long(1.0 + (2. * sqrt((Pi*Pi) + (alpha*alpha)) / (Pi * width)) /* + 0.5 */); -} - -} // end of namespace Loris - diff --git a/loris_library/Source/src/KaiserWindow.h b/loris_library/Source/src/KaiserWindow.h deleted file mode 100644 index d0ba494..0000000 --- a/loris_library/Source/src/KaiserWindow.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef INCLUDE_KAISERWINDOW_H -#define INCLUDE_KAISERWINDOW_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * KaiserWindow.h - * - * Definition of class Loris::KaiserWindow. - * - * Kelly Fitz, 14 Dec 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class KaiserWindow -// -//! Computes samples of a Kaiser window -//! function (see Kaiser and Schafer, 1980) for windowing FFT data. -// -class KaiserWindow -{ -// -- public interface -- -public: - - // -- window building -- - - //! Build a new Kaiser analysis window having the specified shaping - //! parameter. See Oppenheim and Schafer: "Digital Signal Processing" - //! (1975), p. 452 for further explanation of the Kaiser window. Also, - //! see Kaiser and Schafer, 1980. - //! - //! \param win is the vector that will store the window - //! samples. The number of samples computed will be - //! equal to the length of this vector. Any previous - //! contents will be overwritten. - //! \param shape is the Kaiser shaping parameter, controlling - //! the sidelobe rejection level. - static void buildWindow( std::vector< double > & win, double shape ); - - //! Build a new time-derivative Kaiser analysis window having the - //! specified shaping parameter, for computing frequency reassignment. - //! The closed form for the time derivative can be obtained from the - //! property of modified Bessel functions that the derivative of the - //! zeroeth order function is equal to the first order function. - //! - //! \param win is the vector that will store the window - //! samples. The number of samples computed will be - //! equal to the length of this vector. Any previous - //! contents will be overwritten. - //! \param shape is the Kaiser shaping parameter, controlling - //! the sidelobe rejection level. - static void buildTimeDerivativeWindow( std::vector< double > & win, double shape ); - - - // -- window parameter estimation -- - - //! Compute a shaping parameter that will achieve the specified - //! level of sidelobe rejection. - //! - //! \param atten is the desired sidelobe attenuation in - //! positive decibels (e.g. 65 dB) - //! \returns the Kaiser shaping paramater - static double computeShape( double atten ); - - //! Compute the necessary length in samples of a Kaiser window - //! having the specified shaping parameter that has the - //! desired main lobe width. - //! - //! \param width is the desired main lobe width expressed - //! as a fraction of the sample rate. - //! \param alpha is the Kaiser shaping parameter (the - //! main lobe width is influenced primarily by the - //! window length,but also by the shape). - //! \returns the window length in samples - static unsigned long computeLength( double width, double alpha ); - -// construction is not allowed: -private: - KaiserWindow( void ); - -}; // end of class KaiserWindow - -} // end of namespace Loris - -#endif /* ndef INCLUDE_KAISERWINDOW_H */ diff --git a/loris_library/Source/src/LinearEnvelope.cpp b/loris_library/Source/src/LinearEnvelope.cpp deleted file mode 100644 index 13d59ec..0000000 --- a/loris_library/Source/src/LinearEnvelope.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * LinearEnvelope.C - * - * Implementation of class LinearEnvelope. - * - * Kelly Fitz, 23 April 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "LinearEnvelope.h" - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Construct a new LinearEnvelope having no -//! breakpoints (and an implicit value of 0 everywhere). -// -LinearEnvelope::LinearEnvelope( void ) -{ -} - -// --------------------------------------------------------------------------- -// constructor with initial (or constant) value -// --------------------------------------------------------------------------- -//! Construct and return a new LinearEnvelope having a -//! single breakpoint at 0 (and an implicit value everywhere) -//! of initialValue. -//! -//! \param initialValue is the value of this LinearEnvelope -//! at time 0. -// -LinearEnvelope::LinearEnvelope( double initialValue ) -{ - insertBreakpoint( 0., initialValue ); -} - -// --------------------------------------------------------------------------- -// clone -// --------------------------------------------------------------------------- -//! Return an exact copy of this LinearEnvelope -//! (polymorphic copy, following the Prototype pattern). -// -LinearEnvelope * -LinearEnvelope::clone( void ) const -{ - return new LinearEnvelope( *this ); -} - -// --------------------------------------------------------------------------- -// insert -// --------------------------------------------------------------------------- -//! Insert a breakpoint representing the specified (time, value) -//! pair into this LinearEnvelope. If there is already a -//! breakpoint at the specified time, it will be replaced with -//! the new breakpoint. -//! -//! \param time is the time at which to insert a new breakpoint -//! \param value is the value of the new breakpoint -// -void -LinearEnvelope::insert( double time, double value ) -{ - (*this)[time] = value; -} - -// --------------------------------------------------------------------------- -// operator+= -// --------------------------------------------------------------------------- -//! Add a constant value to this LinearEnvelope and return a reference -//! to self. -//! -//! \param offset is the value to add to all points in the envelope -LinearEnvelope & LinearEnvelope::operator+=( double offset ) -{ - for ( iterator it = begin(); it != end(); ++it ) - { - it->second += offset; - } - return *this; -} - -// --------------------------------------------------------------------------- -// operator*= -// --------------------------------------------------------------------------- -//! Scale this LinearEnvelope by a constant value and return a reference -//! to self. -//! -//! \param scale is the value by which to multiply to all points in -//! the envelope -LinearEnvelope & LinearEnvelope::operator*=( double scale ) -{ - for ( iterator it = begin(); it != end(); ++it ) - { - it->second *= scale; - } - return *this; -} - -// --------------------------------------------------------------------------- -// operator/ (non-member binary operator) -// --------------------------------------------------------------------------- -//! Divide constant value by a LinearEnvelope and return a new -//! LinearEnvelope. No shortcut implementation for this one, -//! don't inline. -LinearEnvelope operator/( double num, LinearEnvelope env ) -{ - for ( LinearEnvelope::iterator it = env.begin(); it != env.end(); ++it ) - { - it->second = num / it->second; - } - - return env; -} - -// --------------------------------------------------------------------------- -// valueAt -// --------------------------------------------------------------------------- -//! Return the linearly-interpolated value of this LinearEnvelope at -//! the specified time. -//! -//! \param t is the time at which to evaluate this LinearEnvelope. -// -double -LinearEnvelope::valueAt( double t ) const -{ - // return zero if no breakpoints have been specified: - if ( size() == 0 ) - { - return 0.; - } - - const_iterator it = lower_bound( t ); - - if ( it == begin() ) - { - // t is less than the first breakpoint, extend: - return it->second; - } - else if ( it == end() ) - { - // t is greater than the last breakpoint, extend: - // (no direct way to access the last element of a map) - return (--it)->second; - } - else - { - // linear interpolation between consecutive breakpoints: - double xgreater = it->first; - double ygreater = it->second; - --it; - double xless = it->first; - double yless = it->second; - - double alpha = (t - xless) / (xgreater - xless); - return ( alpha * ygreater ) + ( (1. - alpha) * yless ); - } -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/LinearEnvelope.h b/loris_library/Source/src/LinearEnvelope.h deleted file mode 100644 index be06f69..0000000 --- a/loris_library/Source/src/LinearEnvelope.h +++ /dev/null @@ -1,303 +0,0 @@ -#ifndef INCLUDE_LINEARENVELOPE_H -#define INCLUDE_LINEARENVELOPE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * LinearEnvelope.h - * - * Definition of class LinearEnvelope. - * - * Kelly Fitz, 23 April 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Envelope.h" -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class LinearEnvelope -// -//! A LinearEnvelope represents a linear segment breakpoint function -//! with infinite extension at each end (that is, evalutaing the -//! envelope past either end of the breakpoint function yields the -//! value at the nearest end point). -//! -//! LinearEnvelope implements the Envelope interface, described -//! by the abstract class Envelope. -//! -//! LinearEnvelope inherits the types -//! \li \c size_type -//! \li \c value_type -//! \li \c iterator -//! \li \c const_iterator -//! -//! and the member functions -//! \li size_type size( void ) const -//! \li bool empty( void ) const -//! \li iterator begin( void ) -//! \li const_iterator begin( void ) const -//! \li iterator end( void ) -//! \li const_iterator end( void ) const -//! -//! from std::map< double, double >. -// -class LinearEnvelope : public Envelope, private std::map< double, double > -{ -// -- public interface -- -public: -// -- construction -- - - //! Construct a new LinearEnvelope having no - //! breakpoints (and an implicit value of 0 everywhere). - LinearEnvelope( void ); - - //! Construct and return a new LinearEnvelope having a - //! single breakpoint at 0 (and an implicit value everywhere) - //! of initialValue. - //! - //! \param initialValue is the value of this LinearEnvelope - //! at time 0. - explicit LinearEnvelope( double initialValue ); - - // compiler-generated copy, assignment, and destruction are OK. - -// -- Envelope interface -- - - //! Return an exact copy of this LinearEnvelope - //! (polymorphic copy, following the Prototype pattern). - virtual LinearEnvelope * clone( void ) const; - - //! Return the linearly-interpolated value of this LinearEnvelope at - //! the specified time. - //! - //! \param t is the time at which to evaluate this - //! LinearEnvelope. - virtual double valueAt( double t ) const; - - -// -- envelope composition -- - - //! Insert a breakpoint representing the specified (time, value) - //! pair into this LinearEnvelope. If there is already a - //! breakpoint at the specified time, it will be replaced with - //! the new breakpoint. - //! - //! \param time is the time at which to insert a new breakpoint - //! \param value is the value of the new breakpoint - void insert( double time, double value ); - - //! Insert a breakpoint representing the specified (time, value) - //! pair into this LinearEnvelope. Same as insert, retained - //! for backwards-compatibility. - //! - //! \param time is the time at which to insert a new breakpoint - //! \param value is the value of the new breakpoint - void insertBreakpoint( double time, double value ) - { insert( time, value ); } - - - //! Add a constant value to this LinearEnvelope and return a reference - //! to self. - //! - //! \param offset is the value to add to all points in the envelope - LinearEnvelope & operator+=( double offset ); - - //! Subtract a constant value from this LinearEnvelope and return a reference - //! to self. - //! - //! \param offset is the value to subtract from all points in the envelope - LinearEnvelope & operator-=( double offset ) - { - return operator+=( -offset ); - } - - //! Scale this LinearEnvelope by a constant value and return a reference - //! to self. - //! - //! \param scale is the value by which to multiply to all points in - //! the envelope - LinearEnvelope & operator*=( double scale ); - - //! Divide this LinearEnvelope by a constant value and return a reference - //! to self. - //! - //! \param div is the value by which to divide to all points in - //! the envelope - LinearEnvelope & operator/=( double div ) - { - return operator*=( 1.0 / div ); - } - -// -- interface inherited from std::map -- - - using std::map< double, double >::size; - using std::map< double, double >::empty; - using std::map< double, double >::clear; - using std::map< double, double >::begin; - using std::map< double, double >::end; - using std::map< double, double >::size_type; - using std::map< double, double >::value_type; - using std::map< double, double >::iterator; - using std::map< double, double >::const_iterator; - -}; // end of class LinearEnvelope - - -// -- binary operators (inline nonmembers) -- - -//! Add a constant value to a LinearEnvelope and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator+( LinearEnvelope env, double offset ) -{ - env += offset; - return env; -} - -//! Add a constant value to a LinearEnvelope and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator+( double offset, LinearEnvelope env ) -{ - env += offset; - return env; -} - -//! Add two LinearEnvelopes and return a new LinearEnvelope. -inline -LinearEnvelope operator+( const LinearEnvelope & e1, const LinearEnvelope & e2 ) -{ - LinearEnvelope ret; - - // For each breakpoint in e1, insert a breakpoint having a value - // equal to the sum of the two envelopes at that time. - for ( LinearEnvelope::const_iterator it = e1.begin(); it != e1.end(); ++it ) - { - double t = it->first; - double v = it->second; - - ret.insert( t, v + e2.valueAt( t ) ); - } - - // For each breakpoint in e2, insert a breakpoint having a value - // equal to the sum of the two envelopes at that time. - for ( LinearEnvelope::const_iterator it = e2.begin(); it != e2.end(); ++it ) - { - double t = it->first; - double v = it->second; - - ret.insert( t, v + e1.valueAt( t ) ); - } - - return ret; -} - -//! Subtract a constant value from a LinearEnvelope and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator-( LinearEnvelope env, double offset ) -{ - env -= offset; - return env; -} - -//! Subtract a LinearEnvelope from a constant value and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator-( double offset, LinearEnvelope env ) -{ - env *= -1.0; - env += offset; - return env; -} - -//! Subtract two LinearEnvelopes and return a new LinearEnvelope. -inline -LinearEnvelope operator-( const LinearEnvelope & e1, const LinearEnvelope & e2 ) -{ - LinearEnvelope ret; - - // For each breakpoint in e1, insert a breakpoint having a value - // equal to the difference between the two envelopes at that time. - for ( LinearEnvelope::const_iterator it = e1.begin(); it != e1.end(); ++it ) - { - double t = it->first; - double v = it->second; - - ret.insert( t, v - e2.valueAt( t ) ); - } - - // For each breakpoint in e2, insert a breakpoint having a value - // equal to the difference between the two envelopes at that time. - for ( LinearEnvelope::const_iterator it = e2.begin(); it != e2.end(); ++it ) - { - double t = it->first; - double v = it->second; - - ret.insert( t, e1.valueAt( t ) - v ); - } - - return ret; -} - -//! Scale a LinearEnvelope by a constant value and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator*( LinearEnvelope env, double scale ) -{ - env *= scale; - return env; -} - -//! Scale a LinearEnvelope by a constant value and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator*( double scale, LinearEnvelope env ) -{ - env *= scale; - return env; -} - -//! Divide a LinearEnvelope by a constant value and return a new -//! LinearEnvelope. -inline -LinearEnvelope operator/( LinearEnvelope env, double div ) -{ - env /= div; - return env; -} - -//! Divide constant value by a LinearEnvelope and return a new -//! LinearEnvelope. No shortcut implementation for this one, -//! don't inline. -LinearEnvelope operator/( double scale, LinearEnvelope env ); - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_LINEARENVELOPE_H */ diff --git a/loris_library/Source/src/LorisExceptions.cpp b/loris_library/Source/src/LorisExceptions.cpp deleted file mode 100644 index ccccba4..0000000 --- a/loris_library/Source/src/LorisExceptions.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * LorisExceptions.C - * - * Implementation of class Exception, a generic exception class. - * - * This file was formerly called Exception.C, and had a corresponding header - * called Exception.h but that filename caused build problems on case-insensitive - * systems that sometimes had system headers called exception.h. So the header - * name was changed to LorisExceptions.h, and this source files name was - * changed to match. - * - * Kelly Fitz, 17 Oct 2006 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "LorisExceptions.h" -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// Exception constructor -// --------------------------------------------------------------------------- -//! Construct a new instance with the specified description and, optionally -//! a string identifying the location at which the exception as thrown. The -//! Throw( Exception_Class, description_string ) macro generates a location -//! string automatically using __FILE__ and __LINE__. -//! -//! \param str is a string describing the exceptional condition -//! \param where is an option string describing the location in -//! the source code from which the exception was thrown -//! (generated automatically byt he Throw macro). -// -Exception::Exception( const std::string & str, const std::string & where ) : - _sbuf( str ) -{ - _sbuf.append( where ); - _sbuf.append(" "); -} - -// --------------------------------------------------------------------------- -// append -// --------------------------------------------------------------------------- -//! Append the specified string to this Exception's description, -//! and return a reference to this Exception. -//! -//! \param str is text to append to the exception description -//! \return a reference to this Exception. -// -Exception & -Exception::append( const std::string & str ) -{ - _sbuf.append(str); - return *this; -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/LorisExceptions.h b/loris_library/Source/src/LorisExceptions.h deleted file mode 100644 index d0537e0..0000000 --- a/loris_library/Source/src/LorisExceptions.h +++ /dev/null @@ -1,308 +0,0 @@ -#ifndef INCLUDE_EXCEPTIONS_H -#define INCLUDE_EXCEPTIONS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * LorisExceptions.h - * - * Definition of class Exception, a generic exception class, and - * commonly-used derived exception classes. - * - * This file was formerly called Exception.h, but that filename caused build - * problems on case-insensitive systems that sometimes had system headers - * called exception.h. - * - * Kelly Fitz, 17 Oct 2006 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Exception -// -//! Exception is a generic exception class for reporting exceptional -//! circumstances in Loris. Exception is derived from std:exception, -//! and is the base for a hierarchy of derived exception classes -//! in Loris. -//! -// -class Exception : public std::exception -{ -// -- public interface -- -public: -// --- lifecycle --- - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - Exception( const std::string & str, const std::string & where = "" ); - - //! Destroy this Exception. - virtual ~Exception( void ) throw() - { - } - -// --- access/mutation --- - - //! Return a description of this Exception in the form of a - //! C-style string (char pointer). Overrides std::exception::what. - //! - //! \return a C-style string describing the exceptional condition. - const char * what( void ) const throw() { return _sbuf.c_str(); } - - //! Append the specified string to this Exception's description, - //! and return a reference to this Exception. - //! - //! \param str is text to append to the exception description - //! \return a reference to this Exception. - Exception & append( const std::string & str ); - - //! Return a read-only refernce to this Exception's - //! description string. - //! - //! \return a string describing the exceptional condition - const std::string & str( void ) const - { - return _sbuf; - } - -// -- instance variables -- -protected: - - //! string for storing the exception description - std::string _sbuf; - -}; // end of class Exception - -// --------------------------------------------------------------------------- -// class AssertionFailure -// -//! Class of exceptions thrown when an assertion (usually representing an -//! invariant condition, and usually detected by the Assert macro) is -//! violated. -// -class AssertionFailure : public Exception -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - AssertionFailure( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Assertion failed -- ").append( str ), where ) - { - } - -}; // end of class AssertionFailure - -// --------------------------------------------------------------------------- -// class IndexOutOfBounds -// -//! Class of exceptions thrown when a subscriptable object is accessed -//! with an index that is out of range. -// -class IndexOutOfBounds : public Exception -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - IndexOutOfBounds( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Index out of bounds -- ").append( str ), where ) {} - -}; // end of class IndexOutOfBounds - - -// --------------------------------------------------------------------------- -// class InvalidObject -// -//! Class of exceptions thrown when an object is found to be badly configured -//! or otherwise invalid. -// -class InvalidObject : public Exception -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - InvalidObject( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Invalid configuration or object -- ").append( str ), where ) - { - } - -}; // end of class InvalidObject - -// --------------------------------------------------------------------------- -// class InvalidIterator -// -//! Class of exceptions thrown when an Iterator is found to be badly configured -//! or otherwise invalid. -// -class InvalidIterator : public InvalidObject -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - InvalidIterator( const std::string & str, const std::string & where = "" ) : - InvalidObject( std::string("Invalid Iterator -- ").append( str ), where ) - { - } - -}; // end of class InvalidIterator - -// --------------------------------------------------------------------------- -// class InvalidArgument -// -//! Class of exceptions thrown when a function argument is found to be invalid. -// -class InvalidArgument : public Exception -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - InvalidArgument( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Invalid Argument -- ").append( str ), where ) - { - } - -}; // end of class InvalidArgument - -// --------------------------------------------------------------------------- -// class RuntimeError -// -//! Class of exceptions thrown when an unanticipated runtime error is -//! encountered. -// -class RuntimeError : public Exception -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - RuntimeError( const std::string & str, const std::string & where = "" ) : - Exception( std::string("Runtime Error -- ").append( str ), where ) - { - } - -}; // end of class RuntimeError - -// --------------------------------------------------------------------------- -// class FileIOException -// -//! Class of exceptions thrown when file input or output fails. -// -class FileIOException : public RuntimeError -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically by the Throw macro). - FileIOException( const std::string & str, const std::string & where = "" ) : - RuntimeError( std::string("File i/o error -- ").append( str ), where ) - { - } - -}; // end of class FileIOException - -// --------------------------------------------------------------------------- -// macros for throwing exceptions -// -// The compelling reason for using macros instead of inlines for all these -// things is that the __FILE__ and __LINE__ macros will be useful. -// -#define __STR(x) __VAL(x) -#define __VAL(x) #x -#define Throw( exType, report ) \ - throw exType( report, " ( " __FILE__ " line: " __STR(__LINE__) " )" ) - -#define Assert(test) \ - do { \ - if (!(test)) Throw( Loris::AssertionFailure, #test ); \ - } while (false) - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_EXCEPTIONS_H */ diff --git a/loris_library/Source/src/Makefile.am b/loris_library/Source/src/Makefile.am deleted file mode 100644 index 1dd3986..0000000 --- a/loris_library/Source/src/Makefile.am +++ /dev/null @@ -1,163 +0,0 @@ -# Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken -# -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# source code for Loris classes -CPP_SRC = AiffData.C \ - AiffData.h \ - AiffFile.C \ - AiffFile.h \ - Analyzer.C \ - Analyzer.h \ - AssociateBandwidth.C \ - AssociateBandwidth.h \ - BigEndian.C \ - BigEndian.h \ - Breakpoint.C \ - Breakpoint.h \ - BreakpointEnvelope.h \ - BreakpointUtils.C \ - BreakpointUtils.h \ - Channelizer.C \ - Channelizer.h \ - Collator.C \ - Collator.h \ - Dilator.C \ - Dilator.h \ - Distiller.C \ - Distiller.h \ - Envelope.C \ - Envelope.h \ - F0Estimate.C \ - F0Estimate.h \ - LorisExceptions.C \ - LorisExceptions.h \ - Filter.C \ - Filter.h \ - FourierTransform.C \ - FourierTransform.h \ - FrequencyReference.C \ - FrequencyReference.h \ - Fundamental.C \ - Fundamental.h \ - Harmonifier.C \ - Harmonifier.h \ - ImportLemur.C \ - ImportLemur.h \ - KaiserWindow.C \ - KaiserWindow.h \ - LinearEnvelope.C \ - LinearEnvelope.h \ - Marker.C \ - Marker.h \ - Morpher.C \ - Morpher.h \ - NoiseGenerator.C \ - NoiseGenerator.h \ - Notifier.C \ - Notifier.h \ - Oscillator.C \ - Oscillator.h \ - Partial.C \ - Partial.h \ - PartialBuilder.C \ - PartialBuilder.h \ - PartialList.h \ - PartialPtrs.h \ - PartialUtils.C \ - PartialUtils.h \ - phasefix.C \ - phasefix.h \ - ReassignedSpectrum.C \ - ReassignedSpectrum.h \ - Resampler.C \ - Resampler.h \ - SdifFile.h \ - SdifFile.C \ - Sieve.h \ - Sieve.C \ - SpcFile.C \ - SpcFile.h \ - SpectralPeaks.h \ - SpectralPeakSelector.C \ - SpectralPeakSelector.h \ - SpectralSurface.C \ - SpectralSurface.h \ - Synthesizer.C \ - Synthesizer.h \ - fftsg.c - - -# source code for the procedural (C) interface -PI_SRC = loris.h lorisAnalyzer_pi.C lorisBpEnvelope_pi.C \ - lorisException_pi.C lorisException_pi.h lorisNonObj_pi.C \ - lorisPartialList_pi.C lorisUtilities_pi.C - - -# convenience library containing Csound opcodes -if HAVE_CSOUND -CSOUND_LIB = $(top_builddir)/csound/liblorisops.la -endif - - -lib_LTLIBRARIES = libloris.la -libloris_la_SOURCES = $(CPP_SRC) $(PI_SRC) -libloris_la_CPPFLAGS = $(INCLUDE_FFTW) $(default_includes) -libloris_la_LIBADD = $(LINK_FFTW) $(CSOUND_LIB) - -# the library version for Loris 1.8 is 13:0:0 -libloris_la_LDFLAGS = -version-info 13:0:0 $(EXTRA_LD_FLAGS) - -# loris.h is generated automatically from loris.h.in -nodist_include_HEADERS = loris.h -EXTRA_DIST = loris.h.in - -# installed Loris header files -pkginclude_HEADERS = \ - AiffFile.h \ - Analyzer.h \ - BreakpointEnvelope.h \ - Breakpoint.h \ - BreakpointUtils.h \ - Channelizer.h \ - Collator.h \ - Dilator.h \ - Distiller.h \ - Envelope.h \ - Exception.h \ - F0Estimate.h \ - Filter.h \ - FourierTransform.h \ - FrequencyReference.h \ - Fundamental.h \ - Harmonifier.h \ - ImportLemur.h \ - KaiserWindow.h \ - LinearEnvelope.h \ - LorisExceptions.h \ - Marker.h \ - Morpher.h \ - NoiseGenerator.h \ - Notifier.h \ - Oscillator.h \ - Partial.h \ - PartialList.h \ - PartialPtrs.h \ - PartialUtils.h \ - ReassignedSpectrum.h \ - Resampler.h \ - SdifFile.h \ - Sieve.h \ - SpcFile.h \ - SpectralSurface.h \ - Synthesizer.h - -MAINTAINERCLEANFILES = Makefile.in - diff --git a/loris_library/Source/src/Makefile.in b/loris_library/Source/src/Makefile.in deleted file mode 100644 index c66a11d..0000000 --- a/loris_library/Source/src/Makefile.in +++ /dev/null @@ -1,1168 +0,0 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken -# -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src -DIST_COMMON = README $(pkginclude_HEADERS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/loris.h.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = loris.h -CONFIG_CLEAN_VPATH_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" \ - "$(DESTDIR)$(pkgincludedir)" -LTLIBRARIES = $(lib_LTLIBRARIES) -am__DEPENDENCIES_1 = -libloris_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(CSOUND_LIB) -am__objects_1 = libloris_la-AiffData.lo libloris_la-AiffFile.lo \ - libloris_la-Analyzer.lo libloris_la-AssociateBandwidth.lo \ - libloris_la-BigEndian.lo libloris_la-Breakpoint.lo \ - libloris_la-BreakpointUtils.lo libloris_la-Channelizer.lo \ - libloris_la-Collator.lo libloris_la-Dilator.lo \ - libloris_la-Distiller.lo libloris_la-Envelope.lo \ - libloris_la-F0Estimate.lo libloris_la-LorisExceptions.lo \ - libloris_la-Filter.lo libloris_la-FourierTransform.lo \ - libloris_la-FrequencyReference.lo libloris_la-Fundamental.lo \ - libloris_la-Harmonifier.lo libloris_la-ImportLemur.lo \ - libloris_la-KaiserWindow.lo libloris_la-LinearEnvelope.lo \ - libloris_la-Marker.lo libloris_la-Morpher.lo \ - libloris_la-NoiseGenerator.lo libloris_la-Notifier.lo \ - libloris_la-Oscillator.lo libloris_la-Partial.lo \ - libloris_la-PartialBuilder.lo libloris_la-PartialUtils.lo \ - libloris_la-phasefix.lo libloris_la-ReassignedSpectrum.lo \ - libloris_la-Resampler.lo libloris_la-SdifFile.lo \ - libloris_la-Sieve.lo libloris_la-SpcFile.lo \ - libloris_la-SpectralPeakSelector.lo \ - libloris_la-SpectralSurface.lo libloris_la-Synthesizer.lo \ - libloris_la-fftsg.lo -am__objects_2 = libloris_la-lorisAnalyzer_pi.lo \ - libloris_la-lorisBpEnvelope_pi.lo \ - libloris_la-lorisException_pi.lo libloris_la-lorisNonObj_pi.lo \ - libloris_la-lorisPartialList_pi.lo \ - libloris_la-lorisUtilities_pi.lo -am_libloris_la_OBJECTS = $(am__objects_1) $(am__objects_2) -libloris_la_OBJECTS = $(am_libloris_la_OBJECTS) -libloris_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(libloris_la_LDFLAGS) $(LDFLAGS) -o $@ -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/config/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ -SOURCES = $(libloris_la_SOURCES) -DIST_SOURCES = $(libloris_la_SOURCES) -HEADERS = $(nodist_include_HEADERS) $(pkginclude_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CSOUND = @CSOUND@ -CSOUND_CONFIG = @CSOUND_CONFIG@ -CSOUND_CXXFLAGS = @CSOUND_CXXFLAGS@ -CSOUND_PREFIX = @CSOUND_PREFIX@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DOXYGEN = @DOXYGEN@ -DSYMUTIL = @DSYMUTIL@ -ECHO = @ECHO@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIBTOOL_DEPS = @LIBTOOL_DEPS@ -LINK_FFTW = @LINK_FFTW@ -LN_S = @LN_S@ -LORIS_MAJOR_VERSION = @LORIS_MAJOR_VERSION@ -LORIS_MINOR_VERSION = @LORIS_MINOR_VERSION@ -LORIS_SUBMINOR_VERSION = @LORIS_SUBMINOR_VERSION@ -LORIS_VERSION_STR = @LORIS_VERSION_STR@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -NMEDIT = @NMEDIT@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PYFLAGS = @PYFLAGS@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -SWIG = @SWIG@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_aux_dir = @ac_aux_dir@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ - -# source code for Loris classes -CPP_SRC = AiffData.C \ - AiffData.h \ - AiffFile.C \ - AiffFile.h \ - Analyzer.C \ - Analyzer.h \ - AssociateBandwidth.C \ - AssociateBandwidth.h \ - BigEndian.C \ - BigEndian.h \ - Breakpoint.C \ - Breakpoint.h \ - BreakpointEnvelope.h \ - BreakpointUtils.C \ - BreakpointUtils.h \ - Channelizer.C \ - Channelizer.h \ - Collator.C \ - Collator.h \ - Dilator.C \ - Dilator.h \ - Distiller.C \ - Distiller.h \ - Envelope.C \ - Envelope.h \ - F0Estimate.C \ - F0Estimate.h \ - LorisExceptions.C \ - LorisExceptions.h \ - Filter.C \ - Filter.h \ - FourierTransform.C \ - FourierTransform.h \ - FrequencyReference.C \ - FrequencyReference.h \ - Fundamental.C \ - Fundamental.h \ - Harmonifier.C \ - Harmonifier.h \ - ImportLemur.C \ - ImportLemur.h \ - KaiserWindow.C \ - KaiserWindow.h \ - LinearEnvelope.C \ - LinearEnvelope.h \ - Marker.C \ - Marker.h \ - Morpher.C \ - Morpher.h \ - NoiseGenerator.C \ - NoiseGenerator.h \ - Notifier.C \ - Notifier.h \ - Oscillator.C \ - Oscillator.h \ - Partial.C \ - Partial.h \ - PartialBuilder.C \ - PartialBuilder.h \ - PartialList.h \ - PartialPtrs.h \ - PartialUtils.C \ - PartialUtils.h \ - phasefix.C \ - phasefix.h \ - ReassignedSpectrum.C \ - ReassignedSpectrum.h \ - Resampler.C \ - Resampler.h \ - SdifFile.h \ - SdifFile.C \ - Sieve.h \ - Sieve.C \ - SpcFile.C \ - SpcFile.h \ - SpectralPeaks.h \ - SpectralPeakSelector.C \ - SpectralPeakSelector.h \ - SpectralSurface.C \ - SpectralSurface.h \ - Synthesizer.C \ - Synthesizer.h \ - fftsg.c - - -# source code for the procedural (C) interface -PI_SRC = loris.h lorisAnalyzer_pi.C lorisBpEnvelope_pi.C \ - lorisException_pi.C lorisException_pi.h lorisNonObj_pi.C \ - lorisPartialList_pi.C lorisUtilities_pi.C - - -# convenience library containing Csound opcodes -@HAVE_CSOUND_TRUE@CSOUND_LIB = $(top_builddir)/csound/liblorisops.la -lib_LTLIBRARIES = libloris.la -libloris_la_SOURCES = $(CPP_SRC) $(PI_SRC) -libloris_la_CPPFLAGS = $(INCLUDE_FFTW) $(default_includes) -libloris_la_LIBADD = $(LINK_FFTW) $(CSOUND_LIB) - -# the library version for Loris 1.8 is 13:0:0 -libloris_la_LDFLAGS = -version-info 13:0:0 $(EXTRA_LD_FLAGS) - -# loris.h is generated automatically from loris.h.in -nodist_include_HEADERS = loris.h -EXTRA_DIST = loris.h.in - -# installed Loris header files -pkginclude_HEADERS = \ - AiffFile.h \ - Analyzer.h \ - BreakpointEnvelope.h \ - Breakpoint.h \ - BreakpointUtils.h \ - Channelizer.h \ - Collator.h \ - Dilator.h \ - Distiller.h \ - Envelope.h \ - Exception.h \ - F0Estimate.h \ - Filter.h \ - FourierTransform.h \ - FrequencyReference.h \ - Fundamental.h \ - Harmonifier.h \ - ImportLemur.h \ - KaiserWindow.h \ - LinearEnvelope.h \ - LorisExceptions.h \ - Marker.h \ - Morpher.h \ - NoiseGenerator.h \ - Notifier.h \ - Oscillator.h \ - Partial.h \ - PartialList.h \ - PartialPtrs.h \ - PartialUtils.h \ - ReassignedSpectrum.h \ - Resampler.h \ - SdifFile.h \ - Sieve.h \ - SpcFile.h \ - SpectralSurface.h \ - Synthesizer.h - -MAINTAINERCLEANFILES = Makefile.in -all: all-am - -.SUFFIXES: -.SUFFIXES: .C .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -loris.h: $(top_builddir)/config.status $(srcdir)/loris.h.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - list2=; for p in $$list; do \ - if test -f $$p; then \ - list2="$$list2 $$p"; \ - else :; fi; \ - done; \ - test -z "$$list2" || { \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ - } - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -libloris.la: $(libloris_la_OBJECTS) $(libloris_la_DEPENDENCIES) - $(libloris_la_LINK) -rpath $(libdir) $(libloris_la_OBJECTS) $(libloris_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-AiffData.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-AiffFile.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Analyzer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-AssociateBandwidth.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-BigEndian.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Breakpoint.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-BreakpointUtils.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Channelizer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Collator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Dilator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Distiller.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Envelope.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-F0Estimate.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Filter.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-FourierTransform.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-FrequencyReference.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Fundamental.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Harmonifier.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-ImportLemur.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-KaiserWindow.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-LinearEnvelope.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-LorisExceptions.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Marker.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Morpher.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-NoiseGenerator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Notifier.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Oscillator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Partial.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-PartialBuilder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-PartialUtils.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-ReassignedSpectrum.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Resampler.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-SdifFile.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Sieve.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-SpcFile.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-SpectralPeakSelector.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-SpectralSurface.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-Synthesizer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-fftsg.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-lorisAnalyzer_pi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-lorisBpEnvelope_pi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-lorisException_pi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-lorisNonObj_pi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-lorisPartialList_pi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-lorisUtilities_pi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloris_la-phasefix.Plo@am__quote@ - -.C.o: -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< - -.C.obj: -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.C.lo: -@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< - -libloris_la-AiffData.lo: AiffData.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-AiffData.lo -MD -MP -MF $(DEPDIR)/libloris_la-AiffData.Tpo -c -o libloris_la-AiffData.lo `test -f 'AiffData.C' || echo '$(srcdir)/'`AiffData.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-AiffData.Tpo $(DEPDIR)/libloris_la-AiffData.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='AiffData.C' object='libloris_la-AiffData.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-AiffData.lo `test -f 'AiffData.C' || echo '$(srcdir)/'`AiffData.C - -libloris_la-AiffFile.lo: AiffFile.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-AiffFile.lo -MD -MP -MF $(DEPDIR)/libloris_la-AiffFile.Tpo -c -o libloris_la-AiffFile.lo `test -f 'AiffFile.C' || echo '$(srcdir)/'`AiffFile.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-AiffFile.Tpo $(DEPDIR)/libloris_la-AiffFile.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='AiffFile.C' object='libloris_la-AiffFile.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-AiffFile.lo `test -f 'AiffFile.C' || echo '$(srcdir)/'`AiffFile.C - -libloris_la-Analyzer.lo: Analyzer.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Analyzer.lo -MD -MP -MF $(DEPDIR)/libloris_la-Analyzer.Tpo -c -o libloris_la-Analyzer.lo `test -f 'Analyzer.C' || echo '$(srcdir)/'`Analyzer.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Analyzer.Tpo $(DEPDIR)/libloris_la-Analyzer.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Analyzer.C' object='libloris_la-Analyzer.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Analyzer.lo `test -f 'Analyzer.C' || echo '$(srcdir)/'`Analyzer.C - -libloris_la-AssociateBandwidth.lo: AssociateBandwidth.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-AssociateBandwidth.lo -MD -MP -MF $(DEPDIR)/libloris_la-AssociateBandwidth.Tpo -c -o libloris_la-AssociateBandwidth.lo `test -f 'AssociateBandwidth.C' || echo '$(srcdir)/'`AssociateBandwidth.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-AssociateBandwidth.Tpo $(DEPDIR)/libloris_la-AssociateBandwidth.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='AssociateBandwidth.C' object='libloris_la-AssociateBandwidth.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-AssociateBandwidth.lo `test -f 'AssociateBandwidth.C' || echo '$(srcdir)/'`AssociateBandwidth.C - -libloris_la-BigEndian.lo: BigEndian.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-BigEndian.lo -MD -MP -MF $(DEPDIR)/libloris_la-BigEndian.Tpo -c -o libloris_la-BigEndian.lo `test -f 'BigEndian.C' || echo '$(srcdir)/'`BigEndian.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-BigEndian.Tpo $(DEPDIR)/libloris_la-BigEndian.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='BigEndian.C' object='libloris_la-BigEndian.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-BigEndian.lo `test -f 'BigEndian.C' || echo '$(srcdir)/'`BigEndian.C - -libloris_la-Breakpoint.lo: Breakpoint.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Breakpoint.lo -MD -MP -MF $(DEPDIR)/libloris_la-Breakpoint.Tpo -c -o libloris_la-Breakpoint.lo `test -f 'Breakpoint.C' || echo '$(srcdir)/'`Breakpoint.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Breakpoint.Tpo $(DEPDIR)/libloris_la-Breakpoint.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Breakpoint.C' object='libloris_la-Breakpoint.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Breakpoint.lo `test -f 'Breakpoint.C' || echo '$(srcdir)/'`Breakpoint.C - -libloris_la-BreakpointUtils.lo: BreakpointUtils.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-BreakpointUtils.lo -MD -MP -MF $(DEPDIR)/libloris_la-BreakpointUtils.Tpo -c -o libloris_la-BreakpointUtils.lo `test -f 'BreakpointUtils.C' || echo '$(srcdir)/'`BreakpointUtils.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-BreakpointUtils.Tpo $(DEPDIR)/libloris_la-BreakpointUtils.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='BreakpointUtils.C' object='libloris_la-BreakpointUtils.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-BreakpointUtils.lo `test -f 'BreakpointUtils.C' || echo '$(srcdir)/'`BreakpointUtils.C - -libloris_la-Channelizer.lo: Channelizer.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Channelizer.lo -MD -MP -MF $(DEPDIR)/libloris_la-Channelizer.Tpo -c -o libloris_la-Channelizer.lo `test -f 'Channelizer.C' || echo '$(srcdir)/'`Channelizer.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Channelizer.Tpo $(DEPDIR)/libloris_la-Channelizer.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Channelizer.C' object='libloris_la-Channelizer.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Channelizer.lo `test -f 'Channelizer.C' || echo '$(srcdir)/'`Channelizer.C - -libloris_la-Collator.lo: Collator.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Collator.lo -MD -MP -MF $(DEPDIR)/libloris_la-Collator.Tpo -c -o libloris_la-Collator.lo `test -f 'Collator.C' || echo '$(srcdir)/'`Collator.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Collator.Tpo $(DEPDIR)/libloris_la-Collator.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Collator.C' object='libloris_la-Collator.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Collator.lo `test -f 'Collator.C' || echo '$(srcdir)/'`Collator.C - -libloris_la-Dilator.lo: Dilator.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Dilator.lo -MD -MP -MF $(DEPDIR)/libloris_la-Dilator.Tpo -c -o libloris_la-Dilator.lo `test -f 'Dilator.C' || echo '$(srcdir)/'`Dilator.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Dilator.Tpo $(DEPDIR)/libloris_la-Dilator.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Dilator.C' object='libloris_la-Dilator.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Dilator.lo `test -f 'Dilator.C' || echo '$(srcdir)/'`Dilator.C - -libloris_la-Distiller.lo: Distiller.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Distiller.lo -MD -MP -MF $(DEPDIR)/libloris_la-Distiller.Tpo -c -o libloris_la-Distiller.lo `test -f 'Distiller.C' || echo '$(srcdir)/'`Distiller.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Distiller.Tpo $(DEPDIR)/libloris_la-Distiller.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Distiller.C' object='libloris_la-Distiller.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Distiller.lo `test -f 'Distiller.C' || echo '$(srcdir)/'`Distiller.C - -libloris_la-Envelope.lo: Envelope.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Envelope.lo -MD -MP -MF $(DEPDIR)/libloris_la-Envelope.Tpo -c -o libloris_la-Envelope.lo `test -f 'Envelope.C' || echo '$(srcdir)/'`Envelope.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Envelope.Tpo $(DEPDIR)/libloris_la-Envelope.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Envelope.C' object='libloris_la-Envelope.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Envelope.lo `test -f 'Envelope.C' || echo '$(srcdir)/'`Envelope.C - -libloris_la-F0Estimate.lo: F0Estimate.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-F0Estimate.lo -MD -MP -MF $(DEPDIR)/libloris_la-F0Estimate.Tpo -c -o libloris_la-F0Estimate.lo `test -f 'F0Estimate.C' || echo '$(srcdir)/'`F0Estimate.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-F0Estimate.Tpo $(DEPDIR)/libloris_la-F0Estimate.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='F0Estimate.C' object='libloris_la-F0Estimate.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-F0Estimate.lo `test -f 'F0Estimate.C' || echo '$(srcdir)/'`F0Estimate.C - -libloris_la-LorisExceptions.lo: LorisExceptions.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-LorisExceptions.lo -MD -MP -MF $(DEPDIR)/libloris_la-LorisExceptions.Tpo -c -o libloris_la-LorisExceptions.lo `test -f 'LorisExceptions.C' || echo '$(srcdir)/'`LorisExceptions.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-LorisExceptions.Tpo $(DEPDIR)/libloris_la-LorisExceptions.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='LorisExceptions.C' object='libloris_la-LorisExceptions.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-LorisExceptions.lo `test -f 'LorisExceptions.C' || echo '$(srcdir)/'`LorisExceptions.C - -libloris_la-Filter.lo: Filter.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Filter.lo -MD -MP -MF $(DEPDIR)/libloris_la-Filter.Tpo -c -o libloris_la-Filter.lo `test -f 'Filter.C' || echo '$(srcdir)/'`Filter.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Filter.Tpo $(DEPDIR)/libloris_la-Filter.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Filter.C' object='libloris_la-Filter.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Filter.lo `test -f 'Filter.C' || echo '$(srcdir)/'`Filter.C - -libloris_la-FourierTransform.lo: FourierTransform.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-FourierTransform.lo -MD -MP -MF $(DEPDIR)/libloris_la-FourierTransform.Tpo -c -o libloris_la-FourierTransform.lo `test -f 'FourierTransform.C' || echo '$(srcdir)/'`FourierTransform.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-FourierTransform.Tpo $(DEPDIR)/libloris_la-FourierTransform.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FourierTransform.C' object='libloris_la-FourierTransform.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-FourierTransform.lo `test -f 'FourierTransform.C' || echo '$(srcdir)/'`FourierTransform.C - -libloris_la-FrequencyReference.lo: FrequencyReference.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-FrequencyReference.lo -MD -MP -MF $(DEPDIR)/libloris_la-FrequencyReference.Tpo -c -o libloris_la-FrequencyReference.lo `test -f 'FrequencyReference.C' || echo '$(srcdir)/'`FrequencyReference.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-FrequencyReference.Tpo $(DEPDIR)/libloris_la-FrequencyReference.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FrequencyReference.C' object='libloris_la-FrequencyReference.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-FrequencyReference.lo `test -f 'FrequencyReference.C' || echo '$(srcdir)/'`FrequencyReference.C - -libloris_la-Fundamental.lo: Fundamental.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Fundamental.lo -MD -MP -MF $(DEPDIR)/libloris_la-Fundamental.Tpo -c -o libloris_la-Fundamental.lo `test -f 'Fundamental.C' || echo '$(srcdir)/'`Fundamental.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Fundamental.Tpo $(DEPDIR)/libloris_la-Fundamental.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Fundamental.C' object='libloris_la-Fundamental.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Fundamental.lo `test -f 'Fundamental.C' || echo '$(srcdir)/'`Fundamental.C - -libloris_la-Harmonifier.lo: Harmonifier.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Harmonifier.lo -MD -MP -MF $(DEPDIR)/libloris_la-Harmonifier.Tpo -c -o libloris_la-Harmonifier.lo `test -f 'Harmonifier.C' || echo '$(srcdir)/'`Harmonifier.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Harmonifier.Tpo $(DEPDIR)/libloris_la-Harmonifier.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Harmonifier.C' object='libloris_la-Harmonifier.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Harmonifier.lo `test -f 'Harmonifier.C' || echo '$(srcdir)/'`Harmonifier.C - -libloris_la-ImportLemur.lo: ImportLemur.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-ImportLemur.lo -MD -MP -MF $(DEPDIR)/libloris_la-ImportLemur.Tpo -c -o libloris_la-ImportLemur.lo `test -f 'ImportLemur.C' || echo '$(srcdir)/'`ImportLemur.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-ImportLemur.Tpo $(DEPDIR)/libloris_la-ImportLemur.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ImportLemur.C' object='libloris_la-ImportLemur.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-ImportLemur.lo `test -f 'ImportLemur.C' || echo '$(srcdir)/'`ImportLemur.C - -libloris_la-KaiserWindow.lo: KaiserWindow.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-KaiserWindow.lo -MD -MP -MF $(DEPDIR)/libloris_la-KaiserWindow.Tpo -c -o libloris_la-KaiserWindow.lo `test -f 'KaiserWindow.C' || echo '$(srcdir)/'`KaiserWindow.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-KaiserWindow.Tpo $(DEPDIR)/libloris_la-KaiserWindow.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='KaiserWindow.C' object='libloris_la-KaiserWindow.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-KaiserWindow.lo `test -f 'KaiserWindow.C' || echo '$(srcdir)/'`KaiserWindow.C - -libloris_la-LinearEnvelope.lo: LinearEnvelope.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-LinearEnvelope.lo -MD -MP -MF $(DEPDIR)/libloris_la-LinearEnvelope.Tpo -c -o libloris_la-LinearEnvelope.lo `test -f 'LinearEnvelope.C' || echo '$(srcdir)/'`LinearEnvelope.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-LinearEnvelope.Tpo $(DEPDIR)/libloris_la-LinearEnvelope.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='LinearEnvelope.C' object='libloris_la-LinearEnvelope.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-LinearEnvelope.lo `test -f 'LinearEnvelope.C' || echo '$(srcdir)/'`LinearEnvelope.C - -libloris_la-Marker.lo: Marker.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Marker.lo -MD -MP -MF $(DEPDIR)/libloris_la-Marker.Tpo -c -o libloris_la-Marker.lo `test -f 'Marker.C' || echo '$(srcdir)/'`Marker.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Marker.Tpo $(DEPDIR)/libloris_la-Marker.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Marker.C' object='libloris_la-Marker.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Marker.lo `test -f 'Marker.C' || echo '$(srcdir)/'`Marker.C - -libloris_la-Morpher.lo: Morpher.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Morpher.lo -MD -MP -MF $(DEPDIR)/libloris_la-Morpher.Tpo -c -o libloris_la-Morpher.lo `test -f 'Morpher.C' || echo '$(srcdir)/'`Morpher.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Morpher.Tpo $(DEPDIR)/libloris_la-Morpher.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Morpher.C' object='libloris_la-Morpher.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Morpher.lo `test -f 'Morpher.C' || echo '$(srcdir)/'`Morpher.C - -libloris_la-NoiseGenerator.lo: NoiseGenerator.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-NoiseGenerator.lo -MD -MP -MF $(DEPDIR)/libloris_la-NoiseGenerator.Tpo -c -o libloris_la-NoiseGenerator.lo `test -f 'NoiseGenerator.C' || echo '$(srcdir)/'`NoiseGenerator.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-NoiseGenerator.Tpo $(DEPDIR)/libloris_la-NoiseGenerator.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='NoiseGenerator.C' object='libloris_la-NoiseGenerator.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-NoiseGenerator.lo `test -f 'NoiseGenerator.C' || echo '$(srcdir)/'`NoiseGenerator.C - -libloris_la-Notifier.lo: Notifier.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Notifier.lo -MD -MP -MF $(DEPDIR)/libloris_la-Notifier.Tpo -c -o libloris_la-Notifier.lo `test -f 'Notifier.C' || echo '$(srcdir)/'`Notifier.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Notifier.Tpo $(DEPDIR)/libloris_la-Notifier.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Notifier.C' object='libloris_la-Notifier.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Notifier.lo `test -f 'Notifier.C' || echo '$(srcdir)/'`Notifier.C - -libloris_la-Oscillator.lo: Oscillator.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Oscillator.lo -MD -MP -MF $(DEPDIR)/libloris_la-Oscillator.Tpo -c -o libloris_la-Oscillator.lo `test -f 'Oscillator.C' || echo '$(srcdir)/'`Oscillator.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Oscillator.Tpo $(DEPDIR)/libloris_la-Oscillator.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Oscillator.C' object='libloris_la-Oscillator.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Oscillator.lo `test -f 'Oscillator.C' || echo '$(srcdir)/'`Oscillator.C - -libloris_la-Partial.lo: Partial.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Partial.lo -MD -MP -MF $(DEPDIR)/libloris_la-Partial.Tpo -c -o libloris_la-Partial.lo `test -f 'Partial.C' || echo '$(srcdir)/'`Partial.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Partial.Tpo $(DEPDIR)/libloris_la-Partial.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Partial.C' object='libloris_la-Partial.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Partial.lo `test -f 'Partial.C' || echo '$(srcdir)/'`Partial.C - -libloris_la-PartialBuilder.lo: PartialBuilder.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-PartialBuilder.lo -MD -MP -MF $(DEPDIR)/libloris_la-PartialBuilder.Tpo -c -o libloris_la-PartialBuilder.lo `test -f 'PartialBuilder.C' || echo '$(srcdir)/'`PartialBuilder.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-PartialBuilder.Tpo $(DEPDIR)/libloris_la-PartialBuilder.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PartialBuilder.C' object='libloris_la-PartialBuilder.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-PartialBuilder.lo `test -f 'PartialBuilder.C' || echo '$(srcdir)/'`PartialBuilder.C - -libloris_la-PartialUtils.lo: PartialUtils.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-PartialUtils.lo -MD -MP -MF $(DEPDIR)/libloris_la-PartialUtils.Tpo -c -o libloris_la-PartialUtils.lo `test -f 'PartialUtils.C' || echo '$(srcdir)/'`PartialUtils.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-PartialUtils.Tpo $(DEPDIR)/libloris_la-PartialUtils.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PartialUtils.C' object='libloris_la-PartialUtils.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-PartialUtils.lo `test -f 'PartialUtils.C' || echo '$(srcdir)/'`PartialUtils.C - -libloris_la-phasefix.lo: phasefix.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-phasefix.lo -MD -MP -MF $(DEPDIR)/libloris_la-phasefix.Tpo -c -o libloris_la-phasefix.lo `test -f 'phasefix.C' || echo '$(srcdir)/'`phasefix.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-phasefix.Tpo $(DEPDIR)/libloris_la-phasefix.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='phasefix.C' object='libloris_la-phasefix.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-phasefix.lo `test -f 'phasefix.C' || echo '$(srcdir)/'`phasefix.C - -libloris_la-ReassignedSpectrum.lo: ReassignedSpectrum.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-ReassignedSpectrum.lo -MD -MP -MF $(DEPDIR)/libloris_la-ReassignedSpectrum.Tpo -c -o libloris_la-ReassignedSpectrum.lo `test -f 'ReassignedSpectrum.C' || echo '$(srcdir)/'`ReassignedSpectrum.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-ReassignedSpectrum.Tpo $(DEPDIR)/libloris_la-ReassignedSpectrum.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ReassignedSpectrum.C' object='libloris_la-ReassignedSpectrum.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-ReassignedSpectrum.lo `test -f 'ReassignedSpectrum.C' || echo '$(srcdir)/'`ReassignedSpectrum.C - -libloris_la-Resampler.lo: Resampler.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Resampler.lo -MD -MP -MF $(DEPDIR)/libloris_la-Resampler.Tpo -c -o libloris_la-Resampler.lo `test -f 'Resampler.C' || echo '$(srcdir)/'`Resampler.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Resampler.Tpo $(DEPDIR)/libloris_la-Resampler.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Resampler.C' object='libloris_la-Resampler.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Resampler.lo `test -f 'Resampler.C' || echo '$(srcdir)/'`Resampler.C - -libloris_la-SdifFile.lo: SdifFile.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-SdifFile.lo -MD -MP -MF $(DEPDIR)/libloris_la-SdifFile.Tpo -c -o libloris_la-SdifFile.lo `test -f 'SdifFile.C' || echo '$(srcdir)/'`SdifFile.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-SdifFile.Tpo $(DEPDIR)/libloris_la-SdifFile.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SdifFile.C' object='libloris_la-SdifFile.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-SdifFile.lo `test -f 'SdifFile.C' || echo '$(srcdir)/'`SdifFile.C - -libloris_la-Sieve.lo: Sieve.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Sieve.lo -MD -MP -MF $(DEPDIR)/libloris_la-Sieve.Tpo -c -o libloris_la-Sieve.lo `test -f 'Sieve.C' || echo '$(srcdir)/'`Sieve.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Sieve.Tpo $(DEPDIR)/libloris_la-Sieve.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Sieve.C' object='libloris_la-Sieve.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Sieve.lo `test -f 'Sieve.C' || echo '$(srcdir)/'`Sieve.C - -libloris_la-SpcFile.lo: SpcFile.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-SpcFile.lo -MD -MP -MF $(DEPDIR)/libloris_la-SpcFile.Tpo -c -o libloris_la-SpcFile.lo `test -f 'SpcFile.C' || echo '$(srcdir)/'`SpcFile.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-SpcFile.Tpo $(DEPDIR)/libloris_la-SpcFile.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SpcFile.C' object='libloris_la-SpcFile.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-SpcFile.lo `test -f 'SpcFile.C' || echo '$(srcdir)/'`SpcFile.C - -libloris_la-SpectralPeakSelector.lo: SpectralPeakSelector.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-SpectralPeakSelector.lo -MD -MP -MF $(DEPDIR)/libloris_la-SpectralPeakSelector.Tpo -c -o libloris_la-SpectralPeakSelector.lo `test -f 'SpectralPeakSelector.C' || echo '$(srcdir)/'`SpectralPeakSelector.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-SpectralPeakSelector.Tpo $(DEPDIR)/libloris_la-SpectralPeakSelector.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SpectralPeakSelector.C' object='libloris_la-SpectralPeakSelector.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-SpectralPeakSelector.lo `test -f 'SpectralPeakSelector.C' || echo '$(srcdir)/'`SpectralPeakSelector.C - -libloris_la-SpectralSurface.lo: SpectralSurface.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-SpectralSurface.lo -MD -MP -MF $(DEPDIR)/libloris_la-SpectralSurface.Tpo -c -o libloris_la-SpectralSurface.lo `test -f 'SpectralSurface.C' || echo '$(srcdir)/'`SpectralSurface.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-SpectralSurface.Tpo $(DEPDIR)/libloris_la-SpectralSurface.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SpectralSurface.C' object='libloris_la-SpectralSurface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-SpectralSurface.lo `test -f 'SpectralSurface.C' || echo '$(srcdir)/'`SpectralSurface.C - -libloris_la-Synthesizer.lo: Synthesizer.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-Synthesizer.lo -MD -MP -MF $(DEPDIR)/libloris_la-Synthesizer.Tpo -c -o libloris_la-Synthesizer.lo `test -f 'Synthesizer.C' || echo '$(srcdir)/'`Synthesizer.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-Synthesizer.Tpo $(DEPDIR)/libloris_la-Synthesizer.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Synthesizer.C' object='libloris_la-Synthesizer.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-Synthesizer.lo `test -f 'Synthesizer.C' || echo '$(srcdir)/'`Synthesizer.C - -libloris_la-lorisAnalyzer_pi.lo: lorisAnalyzer_pi.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-lorisAnalyzer_pi.lo -MD -MP -MF $(DEPDIR)/libloris_la-lorisAnalyzer_pi.Tpo -c -o libloris_la-lorisAnalyzer_pi.lo `test -f 'lorisAnalyzer_pi.C' || echo '$(srcdir)/'`lorisAnalyzer_pi.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-lorisAnalyzer_pi.Tpo $(DEPDIR)/libloris_la-lorisAnalyzer_pi.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='lorisAnalyzer_pi.C' object='libloris_la-lorisAnalyzer_pi.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-lorisAnalyzer_pi.lo `test -f 'lorisAnalyzer_pi.C' || echo '$(srcdir)/'`lorisAnalyzer_pi.C - -libloris_la-lorisBpEnvelope_pi.lo: lorisBpEnvelope_pi.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-lorisBpEnvelope_pi.lo -MD -MP -MF $(DEPDIR)/libloris_la-lorisBpEnvelope_pi.Tpo -c -o libloris_la-lorisBpEnvelope_pi.lo `test -f 'lorisBpEnvelope_pi.C' || echo '$(srcdir)/'`lorisBpEnvelope_pi.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-lorisBpEnvelope_pi.Tpo $(DEPDIR)/libloris_la-lorisBpEnvelope_pi.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='lorisBpEnvelope_pi.C' object='libloris_la-lorisBpEnvelope_pi.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-lorisBpEnvelope_pi.lo `test -f 'lorisBpEnvelope_pi.C' || echo '$(srcdir)/'`lorisBpEnvelope_pi.C - -libloris_la-lorisException_pi.lo: lorisException_pi.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-lorisException_pi.lo -MD -MP -MF $(DEPDIR)/libloris_la-lorisException_pi.Tpo -c -o libloris_la-lorisException_pi.lo `test -f 'lorisException_pi.C' || echo '$(srcdir)/'`lorisException_pi.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-lorisException_pi.Tpo $(DEPDIR)/libloris_la-lorisException_pi.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='lorisException_pi.C' object='libloris_la-lorisException_pi.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-lorisException_pi.lo `test -f 'lorisException_pi.C' || echo '$(srcdir)/'`lorisException_pi.C - -libloris_la-lorisNonObj_pi.lo: lorisNonObj_pi.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-lorisNonObj_pi.lo -MD -MP -MF $(DEPDIR)/libloris_la-lorisNonObj_pi.Tpo -c -o libloris_la-lorisNonObj_pi.lo `test -f 'lorisNonObj_pi.C' || echo '$(srcdir)/'`lorisNonObj_pi.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-lorisNonObj_pi.Tpo $(DEPDIR)/libloris_la-lorisNonObj_pi.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='lorisNonObj_pi.C' object='libloris_la-lorisNonObj_pi.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-lorisNonObj_pi.lo `test -f 'lorisNonObj_pi.C' || echo '$(srcdir)/'`lorisNonObj_pi.C - -libloris_la-lorisPartialList_pi.lo: lorisPartialList_pi.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-lorisPartialList_pi.lo -MD -MP -MF $(DEPDIR)/libloris_la-lorisPartialList_pi.Tpo -c -o libloris_la-lorisPartialList_pi.lo `test -f 'lorisPartialList_pi.C' || echo '$(srcdir)/'`lorisPartialList_pi.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-lorisPartialList_pi.Tpo $(DEPDIR)/libloris_la-lorisPartialList_pi.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='lorisPartialList_pi.C' object='libloris_la-lorisPartialList_pi.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-lorisPartialList_pi.lo `test -f 'lorisPartialList_pi.C' || echo '$(srcdir)/'`lorisPartialList_pi.C - -libloris_la-lorisUtilities_pi.lo: lorisUtilities_pi.C -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libloris_la-lorisUtilities_pi.lo -MD -MP -MF $(DEPDIR)/libloris_la-lorisUtilities_pi.Tpo -c -o libloris_la-lorisUtilities_pi.lo `test -f 'lorisUtilities_pi.C' || echo '$(srcdir)/'`lorisUtilities_pi.C -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-lorisUtilities_pi.Tpo $(DEPDIR)/libloris_la-lorisUtilities_pi.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='lorisUtilities_pi.C' object='libloris_la-lorisUtilities_pi.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libloris_la-lorisUtilities_pi.lo `test -f 'lorisUtilities_pi.C' || echo '$(srcdir)/'`lorisUtilities_pi.C - -.c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< - -libloris_la-fftsg.lo: fftsg.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libloris_la-fftsg.lo -MD -MP -MF $(DEPDIR)/libloris_la-fftsg.Tpo -c -o libloris_la-fftsg.lo `test -f 'fftsg.c' || echo '$(srcdir)/'`fftsg.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libloris_la-fftsg.Tpo $(DEPDIR)/libloris_la-fftsg.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fftsg.c' object='libloris_la-fftsg.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libloris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libloris_la-fftsg.lo `test -f 'fftsg.c' || echo '$(srcdir)/'`fftsg.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-nodist_includeHEADERS: $(nodist_include_HEADERS) - @$(NORMAL_INSTALL) - test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" - @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ - $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ - done - -uninstall-nodist_includeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(includedir)" && rm -f $$files -install-pkgincludeHEADERS: $(pkginclude_HEADERS) - @$(NORMAL_INSTALL) - test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" - @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ - $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ - done - -uninstall-pkgincludeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(pkgincludedir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(pkgincludedir)" && rm -f $$files - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) $(HEADERS) -installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(pkgincludedir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-am - -clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-nodist_includeHEADERS \ - install-pkgincludeHEADERS - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: install-libLTLIBRARIES - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-libLTLIBRARIES uninstall-nodist_includeHEADERS \ - uninstall-pkgincludeHEADERS - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libLTLIBRARIES clean-libtool ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am \ - install-libLTLIBRARIES install-man \ - install-nodist_includeHEADERS install-pdf install-pdf-am \ - install-pkgincludeHEADERS install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am \ - uninstall-libLTLIBRARIES uninstall-nodist_includeHEADERS \ - uninstall-pkgincludeHEADERS - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/loris_library/Source/src/Marker.cpp b/loris_library/Source/src/Marker.cpp deleted file mode 100644 index 83ed3e7..0000000 --- a/loris_library/Source/src/Marker.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Marker.cc - * - * Definition of members for Marker and MarkerContainer representing labeled - * time points or temporal features in imported and exported data. Used by - * file I/O classes AiffFile, SdifFile, and SpcFile. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Marker.h" - -// begin namespace -namespace Loris { - -// -- construction -- - -// --------------------------------------------------------------------------- -// Marker - default constructor -// --------------------------------------------------------------------------- -// Default constructor - initialize a Marker at time zero with no label. -// -Marker::Marker( void ) : - m_time( 0. ), - m_name("Untitled Marker") -{ -} - -// --------------------------------------------------------------------------- -// Marker - constructor from time and name -// --------------------------------------------------------------------------- -// Initialize a Marker with the specified time (in seconds) and name. -// -Marker::Marker( double t, const std::string & s ) : - m_time( t ), - m_name( s ) -{ -} - -// --------------------------------------------------------------------------- -// Marker - copy constructor -// --------------------------------------------------------------------------- -// Initialize a Marker that is an exact copy of another Marker, that is, -// having the same time and name. -// -Marker::Marker( const Marker & other ) : - m_time( other.m_time ), - m_name( other.m_name ) -{ -} - -// --------------------------------------------------------------------------- -// assignment operator (operator =) -// --------------------------------------------------------------------------- -// Make this Marker an exact copy, having the same time and name, -// as the Marker rhs. -// -Marker & -Marker::operator=( const Marker & rhs ) -{ - if ( this != &rhs ) - { - // the only imaginable exception that could be generated - // would be an out-of-memory exception at the time of this - // string assignment, reserve memory first, so that if this - // does except, the Marker is unchanged: - m_name.reserve( rhs.m_name.size() ); - m_name = rhs.m_name; - m_time = rhs.m_time; - - } - return *this; -} - -// -- comparison -- - -// --------------------------------------------------------------------------- -// less-than operator (operator <) -// --------------------------------------------------------------------------- -// Return true if this Marker must appear earlier than rhs in a sorted -// collection of Markers, and false otherwise. (Markers are sorted by time.) -// -bool -Marker::operator< ( const Marker & rhs ) const -{ - return m_time < rhs.m_time; -} - -// -- access -- - -// --------------------------------------------------------------------------- -// name -// --------------------------------------------------------------------------- -// Return a reference to the name string for this Marker. -// -std::string & -Marker::name( void ) -{ - return m_name; -} - -// --------------------------------------------------------------------------- -// name (const) -// --------------------------------------------------------------------------- -// Return a const reference to the name string for this Marker. -// -const std::string & -Marker::name( void ) const -{ - return m_name; -} - -// --------------------------------------------------------------------------- -// time -// --------------------------------------------------------------------------- -// Return the time (in seconds) associated with this Marker. -// -double -Marker::time( void ) const -{ - return m_time; -} - -// -- mutation -- - -// --------------------------------------------------------------------------- -// setName -// --------------------------------------------------------------------------- -// Set the name of the Marker. -// -void -Marker::setName( const std::string & s ) -{ - m_name = s; -} - -// --------------------------------------------------------------------------- -// setName -// --------------------------------------------------------------------------- -// Set the time (in seconds) associated with this Marker. -// -void -Marker::setTime( double t ) -{ - m_time = t; -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Marker.h b/loris_library/Source/src/Marker.h deleted file mode 100644 index 6c51a23..0000000 --- a/loris_library/Source/src/Marker.h +++ /dev/null @@ -1,178 +0,0 @@ -#ifndef INCLUDE_MARKER_H -#define INCLUDE_MARKER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Marker.h - * - * Definition of classes Marker and MarkerContainer representing labeled - * time points or temporal features in imported and exported data. Used by - * file I/O classes AiffFile, SdifFile, and SpcFile. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Marker -// -//! Class Marker represents a labeled time point in a set of Partials -//! or a vector of samples. Collections of Markers (see the MarkerContainer -//! definition below) are held by the File I/O classes in Loris (AiffFile, -//! SdifFile, and SpcFile) to identify temporal features in imported -//! and exported data. -// -class Marker -{ -// -- public interface -- -public: -// -- construction -- - - //! Default constructor - initialize a Marker at time zero with no label. - Marker( void ); - - //! Initialize a Marker with the specified time (in seconds) and name. - //! - //! \param t is the time associated with the new Marker - //! \param s is the name associated with the new Marker - Marker( double t, const std::string & s ); - - //! Initialize a Marker that is an exact copy of another Marker, that is, - //! having the same time and name. - //! - //! \param other is the Marker to copy from - Marker( const Marker & other ); - - //! Make this Marker an exact copy, having the same time and name, - //! as the Marker rhs. - //! - //! \param rhs is the Marker to assign from - //! \return reference to self - Marker & operator=( const Marker & rhs ); - -// -- comparison -- - - //! Return true if this Marker must appear earlier than rhs in a sorted - //! collection of Markers, and false otherwise. - //! (Markers are sorted by time.) - //! - //! \param rhs is the Marker to compare with this Marker - //! \return true if this Marker's time is earlier than that of - //! rhs, otherwise false - bool operator< ( const Marker & rhs ) const; - -// -- access -- - - //! Return a reference to the name string - //! for this Marker. - std::string & name( void ); - - //! Return a const reference to the name string - //! for this Marker. - const std::string & name( void ) const; - - //! Return the time (in seconds) associated with this Marker. - double time( void ) const; - - -// -- mutation -- - //! Set the name of the Marker. - void setName( const std::string & s ); - - //! Set the time (in seconds) associated with this Marker. - void setTime( double t ); - -// -- comparitors -- - - //! Comparitor (binary) functor returning true if its first Marker - //! argument should appear before the second in a range sorted - //! by Marker name. - struct compareNameLess : - public std::binary_function< const Marker, const Marker, bool > - { - //! Function call operator, return true if the first Marker - //! argument should appear before the second in a range sorted - //! by Marker name. - bool operator()( const Marker & lhs, const Marker & rhs ) const - { return lhs.name() < rhs.name(); } - }; - - //! old name for compareNameLess, legacy support - //! \deprecated Use compareNameLess instead. - typedef compareNameLess sortByName; - - - //! Comparitor (binary) functor returning true if its first Marker - //! argument should appear before the second in a range sorted - //! by Marker time. - struct compareTimeLess : - public std::binary_function< const Marker, const Marker, bool > - { - //! Function call operator, return true if the first Marker - //! argument should appear before the second in a range sorted - //! by Marker time. - bool operator()( const Marker & lhs, const Marker & rhs ) const - { return lhs.time() < rhs.time(); } - }; - - //! old name for compareTimeLess, legacy support - //! \deprecated Use compareTimeLess instead - typedef compareTimeLess sortByTime; - - //! Predicate functor returning true if the name of a Marker - //! equal to the specified string, and false otherwise. - class isNameEqual : public std::unary_function< const Marker, bool > - { - public: - //! Initialize a new instance with the specified name. - isNameEqual( const std::string & s ) : name(s) {} - - //! Function call operator: evaluate a Marker. - bool operator()( const Marker & m ) const - { return m.name() == name; } - - private: - std::string name; //! the name to compare against - }; - -private: - -// -- implementation -- - - double m_time; //! the time in seconds associated with the Marker - std::string m_name; //! the name of the Marker - -}; // end of class Marker - -} // end of namespace Loris - -#endif /* ndef INCLUDE_MARKER_H */ diff --git a/loris_library/Source/src/Morpher.cpp b/loris_library/Source/src/Morpher.cpp deleted file mode 100644 index 963ea25..0000000 --- a/loris_library/Source/src/Morpher.cpp +++ /dev/null @@ -1,1597 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Morpher.C - * - * Implementation of class Morpher. - * - * Kelly Fitz, 15 Oct 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Morpher.h" -#include "Breakpoint.h" -#include "Envelope.h" -#include "LorisExceptions.h" -#include "Notifier.h" -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" - -#include "phasefix.h" - -#include -#include -#include -#include - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -// begin namespace -namespace Loris { - - -const double Morpher::DefaultFixThreshold = -90; // dB, very low by default - -// shaping parameter, see interpolateAmplitude: -const double Morpher::DefaultAmpShape = 1E-5; - -const double Morpher::DefaultBreakpointGap = 1E-4; // minimum time (sec) between Breakpoints in - // morphed Partials - -// helper declarations -static inline bool partial_is_nonnull( const Partial & p ); - - - -// -- construction -- - -// --------------------------------------------------------------------------- -// Morpher constructor (single morph function) -// --------------------------------------------------------------------------- -// Construct a new Morpher using the same morphing envelope for -// frequency, amplitude, and bandwidth (noisiness). -// -Morpher::Morpher( const Envelope & f ) : - _freqFunction( f.clone() ), - _ampFunction( f.clone() ), - _bwFunction( f.clone() ), - _freqFixThresholdDb( DefaultFixThreshold ), - _logMorphShape( DefaultAmpShape ), - _minBreakpointGapSec( DefaultBreakpointGap ), - _doLogAmpMorphing( true ), - _doLogFreqMorphing( false ) -{ -} - -// --------------------------------------------------------------------------- -// Morpher constructor (distinct morph functions) -// --------------------------------------------------------------------------- -// Construct a new Morpher using the specified morphing envelopes for -// frequency, amplitude, and bandwidth (noisiness). -// -Morpher::Morpher( const Envelope & ff, const Envelope & af, const Envelope & bwf ) : - _freqFunction( ff.clone() ), - _ampFunction( af.clone() ), - _bwFunction( bwf.clone() ), - _freqFixThresholdDb( DefaultFixThreshold ), - _logMorphShape( DefaultAmpShape ), - _minBreakpointGapSec( DefaultBreakpointGap ), - _doLogAmpMorphing( true ), - _doLogFreqMorphing( false ) -{ -} - -// --------------------------------------------------------------------------- -// Morpher copy constructor -// --------------------------------------------------------------------------- -//! Construct a new Morpher that is a duplicate of rhs. -//! -//! \param rhs is the Morpher to duplicate -Morpher::Morpher( const Morpher & rhs ) : - _freqFunction( rhs._freqFunction->clone() ), - _ampFunction( rhs._ampFunction->clone() ), - _bwFunction( rhs._bwFunction->clone() ), - _srcRefPartial( rhs._srcRefPartial ), - _tgtRefPartial( rhs._tgtRefPartial ), - _freqFixThresholdDb( rhs._freqFixThresholdDb ), - _logMorphShape( rhs._logMorphShape ), - _minBreakpointGapSec( rhs._minBreakpointGapSec ), - _doLogAmpMorphing( rhs._doLogAmpMorphing ), - _doLogFreqMorphing( rhs._doLogFreqMorphing ) -{ -} - -// --------------------------------------------------------------------------- -// Morpher destructor -// --------------------------------------------------------------------------- -// Destroy this Morpher. -// -Morpher::~Morpher( void ) -{ -} - -// --------------------------------------------------------------------------- -// Morpher assignment operator -// --------------------------------------------------------------------------- -//! Make this Morpher a duplicate of rhs. -//! -//! \param rhs is the Morpher to duplicate -Morpher & -Morpher::operator= ( const Morpher & rhs ) -{ - if ( &rhs != this ) - { - _freqFunction.reset( rhs._freqFunction->clone() ); - _ampFunction.reset( rhs._ampFunction->clone() ); - _bwFunction.reset( rhs._bwFunction->clone() ); - - _srcRefPartial = rhs._srcRefPartial; - _tgtRefPartial = rhs._tgtRefPartial; - - _freqFixThresholdDb = rhs._freqFixThresholdDb; - _logMorphShape = rhs._logMorphShape; - _minBreakpointGapSec = rhs._minBreakpointGapSec; - - _doLogAmpMorphing = rhs._doLogAmpMorphing; - _doLogFreqMorphing = rhs._doLogFreqMorphing; - - } - return *this; -} - - - -// -- Partial morphing -- - -// --------------------------------------------------------------------------- -// morphPartials -// --------------------------------------------------------------------------- -//! Morph a pair of Partials to yield a new morphed Partial. -//! Dummy Partials (having no Breakpoints) don't contribute to the -//! morph, except to cause their opposite to fade out. -//! Either (or neither) the source or target Partial may be a dummy -//! Partial (no Breakpoints), but not both. The morphed -//! Partial has Breakpoints at times corresponding to every Breakpoint -//! in both source Partials, omitting Breakpoints that would be -//! closer than the minBreakpointGap to their predecessor. -//! The new morphed Partial is assigned the specified label and returned. -//! -//! \param src is the Partial corresponding to a morph function -//! value of 0, evaluated at the specified time. -//! \param tgt is the Partial corresponding to a morph function -//! value of 1, evaluated at the specified time. -//! \param assignLabel is the label assigned to the morphed Partial -//! \return the morphed Partial -// -Partial -Morpher::morphPartials( Partial src, Partial tgt, int assignLabel ) -{ - if ( (src.numBreakpoints() == 0) && (tgt.numBreakpoints() == 0) ) - { - Throw( InvalidArgument, "Cannot morph two empty Partials," ); - } - - Partial::const_iterator src_iter = src.begin(); - Partial::const_iterator tgt_iter = tgt.begin(); - - // find the earliest time that a Breakpoint - // could be added to the morph: - double dontAddBefore = 0; - if ( 0 < src.numBreakpoints() ) - { - dontAddBefore = std::min( dontAddBefore, src_iter.time() ); - } - if ( 0 < tgt.numBreakpoints() ) - { - dontAddBefore = std::min( dontAddBefore, tgt_iter.time() ); - } - - - // make a new Partial: - Partial newp; - newp.setLabel( assignLabel ); - - - // Merge Breakpoints from the two Partials, - // loop until there are no more Breakpoints to - // consider in either Partial. - while ( src_iter != src.end() || tgt_iter != tgt.end() ) - { - if ( ( tgt_iter == tgt.end() ) || - ( src_iter != src.end() && src_iter.time() < tgt_iter.time() ) ) - { - // Ran out of tgt Breakpoints, or - // src Breakpoint is earlier, add it. - // - // Don't insert Breakpoints arbitrarily close together, - // only insert a new Breakpoint if it is later than - // the end of the new Partial by more than the gap time. - if ( dontAddBefore <= src_iter.time() ) - { - appendMorphedSrc( src_iter.breakpoint(), tgt, src_iter.time(), newp ); - } - - ++src_iter; - } - else - { - // Ran out of src Breakpoints, or - // tgt Breakpoint is earlier add it. - // - // Don't insert Breakpoints arbitrarily close together, - // only insert a new Breakpoint if it is later than - // the end of the new Partial by more than the gap time. - if ( dontAddBefore <= tgt_iter.time() ) - { - appendMorphedTgt( tgt_iter.breakpoint(), src, tgt_iter.time(), newp ); - } - - ++tgt_iter; - } - - if ( 0 != newp.numBreakpoints() ) - { - // update the earliest time the next Breakpoint - // could be added to the morph: - dontAddBefore = newp.endTime() + _minBreakpointGapSec; - } - } - - // Recompute the phases to match the sources when the frequency - // morphing function is 0 or 1. - fixMorphedPhases( newp ); - - return newp; -} - - -// --------------------------------------------------------------------------- -// helper - GetMorphState -// --------------------------------------------------------------------------- - -typedef enum { SRC = 0, TGT, INTERP } MorphState; - -static inline MorphState GetMorphState( double fweight ) -{ - if ( fweight <= 0 ) - { - return SRC; - } - else if ( fweight >= 1 ) - { - return TGT; - } - else - { - return INTERP; - } -} - -// --------------------------------------------------------------------------- -// fixMorphedPhases (helper) -// --------------------------------------------------------------------------- -// Recompute phases for a morphed Partial, so that the synthesized phases -// match the source phases as closesly as possible at times when the -// frequency morphing function is equal to 0 or 1. - -void -Morpher::fixMorphedPhases( Partial & newp ) const -{ - if ( 0 != newp.numBreakpoints() ) - { - // set the initial morph state according to the value of the - // frequency function at the time of the first Breakpoint in - // the morphed partial - Partial::iterator bppos = newp.begin(); - Partial::iterator lastPosCorrect = bppos; - MorphState curstate = GetMorphState( _freqFunction->valueAt( bppos.time() ) ); - - // consider each Breakpoint, look for a change in the - // morph state at the time of each Breakpoint - while( ++bppos != newp.end() ) - { - MorphState nxtstate = GetMorphState( _freqFunction->valueAt( bppos.time() ) ); - if ( nxtstate != curstate ) - { - // switch! - if ( INTERP != curstate ) - { - // switch to INTERP - fixPhaseForward( lastPosCorrect, bppos ); - } - else - { - // switch to SRC or TGT - if ( newp.begin() == lastPosCorrect ) - { - // first transition - fixPhaseBackward( lastPosCorrect, bppos ); - } - else - { - // not first transition - fixPhaseBetween( lastPosCorrect, bppos ); - } - } - lastPosCorrect = bppos; - - curstate = nxtstate; - - } - } - - // fix the remaining phases - fixPhaseForward( lastPosCorrect, --bppos ); - } -} - - -// --------------------------------------------------------------------------- -// crossfade -// --------------------------------------------------------------------------- -// Crossfade Partials with no correspondences. -// -// Unlabeled Partials (having label 0) are considered to -// have no correspondences, so they are just faded out, and not -// actually morphed. This is the same as morphing each with an -// empty dummy Partial (having no Breakpoints). -// -// The Partials in the first range are treated as components of the -// source sound, corresponding to a morph function value of 0, and -// those in the second are treated as components of the target sound, -// corresponding to a morph function value of 1. -// -// The crossfaded Partials are stored in the Morpher's PartialList. -// -void -Morpher::crossfade( PartialList::const_iterator beginSrc, - PartialList::const_iterator endSrc, - PartialList::const_iterator beginTgt, - PartialList::const_iterator endTgt, - Partial::label_type label /* default 0 */ ) -{ - Partial nullPartial; - debugger << "crossfading unlabeled (labeled 0) Partials" << endl; - - long debugCounter; - - // crossfade Partials corresponding to a morph weight of 0: - PartialList::const_iterator it; - debugCounter = 0; - for ( it = beginSrc; it != endSrc; ++it ) - { - if ( it->label() == label && 0 != it->numBreakpoints() ) - { - Partial newp; - newp.setLabel( label ); - double dontAddBefore = it->startTime(); - - for ( Partial::const_iterator bpPos = it->begin(); - bpPos != it->end(); - ++bpPos ) - { - // Don't insert Breakpoints arbitrarily close together, - // only insert a new Breakpoint if it is later than - // the end of the new Partial by more than the gap time. - if ( dontAddBefore <= bpPos.time() ) - { - newp.insert( bpPos.time(), - fadeSrcBreakpoint( bpPos.breakpoint(), bpPos.time() ) ); - dontAddBefore = bpPos.time() + _minBreakpointGapSec; - } - } - - if ( newp.numBreakpoints() > 0 ) - { - ++debugCounter; - _partials.push_back( newp ); - } - } - } - debugger << "kept " << debugCounter << " from sound 1" << endl; - - // crossfade Partials corresponding to a morph weight of 1: - debugCounter = 0; - for ( it = beginTgt; it != endTgt; ++it ) - { - if ( it->label() == label && 0 != it->numBreakpoints() ) - { - Partial newp; - newp.setLabel( label ); - double dontAddBefore = it->startTime(); - - for ( Partial::const_iterator bpPos = it->begin(); - bpPos != it->end(); - ++bpPos ) - { - // Don't insert Breakpoints arbitrarily close together, - // only insert a new Breakpoint if it is later than - // the end of the new Partial by more than the gap time. - if ( dontAddBefore <= bpPos.time() ) - { - newp.insert( bpPos.time(), - fadeTgtBreakpoint( bpPos.breakpoint(), bpPos.time() ) ); - dontAddBefore = bpPos.time() + _minBreakpointGapSec; - } - } - - if ( newp.numBreakpoints() > 0 ) - { - ++debugCounter; - _partials.push_back( newp ); - } - } - } - debugger << "kept " << debugCounter << " from sound 2" << endl; -} - -// --------------------------------------------------------------------------- -// morph -// --------------------------------------------------------------------------- -// Morph two sounds (collections of Partials labeled to indicate -// correspondences) into a single labeled collection of Partials. -// Unlabeled Partials (having label 0) are crossfaded. The morphed -// and crossfaded Partials are stored in the Morpher's PartialList. -// -// The Partials in the first range are treated as components of the -// source sound, corresponding to a morph function value of 0, and -// those in the second are treated as components of the target sound, -// corresponding to a morph function value of 1. -// -// Throws InvalidArgument if either the source or target -// sequence is not distilled (contains more than one Partial having -// the same non-zero label). -// -// Ugh! This ought to be a template function! -// Ugh! But then crossfade needs to be a template function. -// Maybe need to do something different with crossfade first. -// -void -Morpher::morph( PartialList::const_iterator beginSrc, - PartialList::const_iterator endSrc, - PartialList::const_iterator beginTgt, - PartialList::const_iterator endTgt ) -{ - // build a PartialCorrespondence, a map of labels - // to pairs of pointers to Partials, by making every - // Partial in the source the first element of the - // pair at the corresponding label, and every Partial - // in the target the second element of the pair at - // the corresponding label. Pointers not assigned to - // point to a Partial in the source or target are - // initialized to 0 in the correspondence map. - PartialCorrespondence correspondence; - - // add source Partials to the correspondence map: - for ( PartialList::const_iterator it = beginSrc; it != endSrc; ++it ) - { - // don't add the crossfade label to the set: - if ( it->label() != 0 ) - { - MorphingPair & match = correspondence[ it->label() ]; - if ( match.src.numBreakpoints() != 0 ) - { - Throw( InvalidArgument, "Source Partials must be distilled before morphing." ); - } - match.src = *it; - } - } - - // add target Partials to the correspondence map: - for ( PartialList::const_iterator it = beginTgt; it != endTgt; ++it ) - { - // don't add the crossfade label to the set: - if ( it->label() != 0 ) - { - MorphingPair & match = correspondence[ it->label() ]; - if ( match.tgt.numBreakpoints() != 0 ) - { - Throw( InvalidArgument, "Target Partials must be distilled before morphing." ); - } - match.tgt = *it; - } - } - - // morph corresponding labeled Partials: - morph_aux( correspondence ); - - // crossfade the remaining unlabeled Partials: - crossfade( beginSrc, endSrc, beginTgt, endTgt ); -} - -// --------------------------------------------------------------------------- -// morphBreakpoints -// --------------------------------------------------------------------------- -//! Compute morphed parameter values at the specified time, using -//! the source and target Breakpoints (assumed to correspond exactly -//! to the specified time). -//! -//! \param srcBkpt is the Breakpoint corresponding to a morph function -//! value of 0. -//! \param tgtBkpt is the Breakpoint corresponding to a morph function -//! value of 1. -//! \param time is the time corresponding to srcBkpt (used -//! to evaluate the morphing functions and tgtPartial). -//! \return the morphed Breakpoint -// -Breakpoint -Morpher::morphBreakpoints( Breakpoint srcBkpt, Breakpoint tgtBkpt, - double time ) const -{ - double fweight = _freqFunction->valueAt( time ); - double aweight = _ampFunction->valueAt( time ); - double bweight = _bwFunction->valueAt( time ); - - // compute interpolated Breakpoint parameters: - return interpolateParameters( srcBkpt, tgtBkpt, fweight, - aweight, bweight ); -} - -// --------------------------------------------------------------------------- -// morphSrcBreakpoint -// --------------------------------------------------------------------------- -//! Compute morphed parameter values at the specified time, using -//! the source Breakpoint (assumed to correspond exactly to the -//! specified time) and the target Partial (whose parameters are -//! examined at the specified time). -//! -//! \pre the target Partial may not be a dummy Partial (no Breakpoints). -//! -//! \param srcBkpt is the Breakpoint corresponding to a morph function -//! value of 0. -//! \param tgtPartial is the Partial corresponding to a morph function -//! value of 1, evaluated at the specified time. -//! \param time is the time corresponding to srcBkpt (used -//! to evaluate the morphing functions and tgtPartial). -//! \return the morphed Breakpoint -// -Breakpoint -Morpher::morphSrcBreakpoint( const Breakpoint & srcBkpt, const Partial & tgtPartial, - double time ) const -{ - if ( 0 == tgtPartial.numBreakpoints() ) - { - Throw( InvalidArgument, "morphSrcBreakpoint cannot morph with empty Partial" ); - } - - Breakpoint tgtBkpt = tgtPartial.parametersAt( time ); - - return morphBreakpoints( srcBkpt, tgtBkpt, time ); -} - -// --------------------------------------------------------------------------- -// morphTgtBreakpoint -// --------------------------------------------------------------------------- -//! Compute morphed parameter values at the specified time, using -//! the target Breakpoint (assumed to correspond exactly to the -//! specified time) and the source Partial (whose parameters are -//! examined at the specified time). -//! -//! \pre the source Partial may not be a dummy Partial (no Breakpoints). -//! -//! \param tgtBkpt is the Breakpoint corresponding to a morph function -//! value of 1. -//! \param srcPartial is the Partial corresponding to a morph function -//! value of 0, evaluated at the specified time. -//! \param time is the time corresponding to srcBkpt (used -//! to evaluate the morphing functions and srcPartial). -//! \return the morphed Breakpoint -// -Breakpoint -Morpher::morphTgtBreakpoint( const Breakpoint & tgtBkpt, const Partial & srcPartial, - double time ) const -{ - if ( 0 == srcPartial.numBreakpoints() ) - { - Throw( InvalidArgument, "morphTgtBreakpoint cannot morph with empty Partial" ); - } - - Breakpoint srcBkpt = srcPartial.parametersAt( time ); - - return morphBreakpoints( srcBkpt, tgtBkpt, time ); -} - -// --------------------------------------------------------------------------- -// fadeSrcBreakpoint -// --------------------------------------------------------------------------- -//! Compute morphed parameter values at the specified time, using -//! the source Breakpoint, assumed to correspond exactly to the -//! specified time, and assuming that there is no corresponding -//! target Partial, so the source Breakpoint should be simply faded. -//! -//! \param bp is the Breakpoint corresponding to a morph function -//! value of 0. -//! \param time is the time corresponding to bp (used -//! to evaluate the morphing functions). -//! \return the faded Breakpoint -// -Breakpoint -Morpher::fadeSrcBreakpoint( Breakpoint bp, double time ) const -{ - double alpha = _ampFunction->valueAt( time ); - bp.setAmplitude( interpolateAmplitude( bp.amplitude(), 0, - alpha ) ); - return bp; -} - -// --------------------------------------------------------------------------- -// fadeTgtBreakpoint -// --------------------------------------------------------------------------- -//! Compute morphed parameter values at the specified time, using -//! the target Breakpoint, assumed to correspond exactly to the -//! specified time, and assuming that there is not corresponding -//! source Partial, so the target Breakpoint should be simply faded. -//! -//! \param bp is the Breakpoint corresponding to a morph function -//! value of 1. -//! \param time is the time corresponding to bp (used -//! to evaluate the morphing functions). -//! \return the faded Breakpoint -// -Breakpoint -Morpher::fadeTgtBreakpoint( Breakpoint bp, double time ) const -{ - double alpha = _ampFunction->valueAt( time ); - bp.setAmplitude( interpolateAmplitude( 0, bp.amplitude(), - alpha ) ); - return bp; -} - -// -- morphing function access/mutation -- - -// --------------------------------------------------------------------------- -// setFrequencyFunction -// --------------------------------------------------------------------------- -// Assign a new frequency morphing envelope to this Morpher. -// -void -Morpher::setFrequencyFunction( const Envelope & f ) -{ - _freqFunction.reset( f.clone() ); -} - -// --------------------------------------------------------------------------- -// setAmplitudeFunction -// --------------------------------------------------------------------------- -// Assign a new amplitude morphing envelope to this Morpher. -// -void -Morpher::setAmplitudeFunction( const Envelope & f ) -{ - _ampFunction.reset( f.clone() ); -} - -// --------------------------------------------------------------------------- -// setBandwidthFunction -// --------------------------------------------------------------------------- -// Assign a new bandwidth morphing envelope to this Morpher. -// -void -Morpher::setBandwidthFunction( const Envelope & f ) -{ - _bwFunction.reset( f.clone() ); -} - -// --------------------------------------------------------------------------- -// frequencyFunction -// --------------------------------------------------------------------------- -// Return a reference to this Morpher's frequency morphing envelope. -// -const Envelope & -Morpher::frequencyFunction( void ) const -{ - return * _freqFunction; -} - -// --------------------------------------------------------------------------- -// amplitudeFunction -// --------------------------------------------------------------------------- -// Return a reference to this Morpher's amplitude morphing envelope. -// -const Envelope & -Morpher::amplitudeFunction( void ) const -{ - return * _ampFunction; -} - -// --------------------------------------------------------------------------- -// bandwidthFunction -// --------------------------------------------------------------------------- -// Return a reference to this Morpher's bandwidth morphing envelope. -// -const Envelope & -Morpher::bandwidthFunction( void ) const -{ - return * _bwFunction; -} - - -// -- reference Partial label access/mutation -- - -// --------------------------------------------------------------------------- -// sourceReferencePartial -// --------------------------------------------------------------------------- -//! Return the Partial to be used as a reference -//! Partial for the source sequence in a morph of two Partial -//! sequences. The reference partial is used to compute -//! frequencies for very low-amplitude Partials whose frequency -//! estimates are not considered reliable. The reference Partial -//! is considered to have good frequency estimates throughout. -//! A default (empty) Partial indicates that no reference Partial -//! should be used for the source sequence. -// -const Partial & -Morpher::sourceReferencePartial( void ) const -{ - return _srcRefPartial; -} - -// --------------------------------------------------------------------------- -// sourceReferencePartial -// --------------------------------------------------------------------------- -//! Return the Partial to be used as a reference -//! Partial for the source sequence in a morph of two Partial -//! sequences. The reference partial is used to compute -//! frequencies for very low-amplitude Partials whose frequency -//! estimates are not considered reliable. The reference Partial -//! is considered to have good frequency estimates throughout. -//! A default (empty) Partial indicates that no reference Partial -//! should be used for the source sequence. -// -Partial & -Morpher::sourceReferencePartial( void ) -{ - return _srcRefPartial; -} - -// --------------------------------------------------------------------------- -// targetReferenceLabel -// --------------------------------------------------------------------------- -//! Return the Partial to be used as a reference -//! Partial for the target sequence in a morph of two Partial -//! sequences. The reference partial is used to compute -//! frequencies for very low-amplitude Partials whose frequency -//! estimates are not considered reliable. The reference Partial -//! is considered to have good frequency estimates throughout. -//! A default (empty) Partial indicates that no reference Partial -//! should be used for the target sequence. -// -const Partial & -Morpher::targetReferencePartial( void ) const -{ - return _tgtRefPartial; -} - -// --------------------------------------------------------------------------- -// targetReferenceLabel -// --------------------------------------------------------------------------- -//! Return the Partial to be used as a reference -//! Partial for the target sequence in a morph of two Partial -//! sequences. The reference partial is used to compute -//! frequencies for very low-amplitude Partials whose frequency -//! estimates are not considered reliable. The reference Partial -//! is considered to have good frequency estimates throughout. -//! A default (empty) Partial indicates that no reference Partial -//! should be used for the target sequence. -// -Partial & -Morpher::targetReferencePartial( void ) -{ - return _tgtRefPartial; -} - -// --------------------------------------------------------------------------- -// setSourceReferencePartial -// --------------------------------------------------------------------------- -//! Specify the Partial to be used as a reference -//! Partial for the source sequence in a morph of two Partial -//! sequences. The reference partial is used to compute -//! frequencies for very low-amplitude Partials whose frequency -//! estimates are not considered reliable. The reference Partial -//! is considered to have good frequency estimates throughout. -//! The specified Partial must be labeled with its harmonic number. -//! A default (empty) Partial indicates that no reference -//! Partial should be used for the source sequence. -// -void -Morpher::setSourceReferencePartial( const Partial & p ) -{ - if ( p.label() == 0 ) - { - Throw( InvalidArgument, - "the morphing source reference Partial must be " - "labeled with its harmonic number" ); - } - _srcRefPartial = p; -} - -// --------------------------------------------------------------------------- -// setSourceReferencePartial -// --------------------------------------------------------------------------- -//! Specify the Partial to be used as a reference -//! Partial for the source sequence in a morph of two Partial -//! sequences. The reference partial is used to compute -//! frequencies for very low-amplitude Partials whose frequency -//! estimates are not considered reliable. The reference Partial -//! is considered to have good frequency estimates throughout. -//! A default (empty) Partial indicates that no reference -//! Partial should be used for the source sequence. -//! -//! \param partials a sequence of Partials to search -//! for the reference Partial -//! \param refLabel the label of the Partial in partials -//! that should be selected as the reference -// -void -Morpher::setSourceReferencePartial( const PartialList & partials, - Partial::label_type refLabel ) -{ - if ( refLabel != 0 ) - { - PartialList::const_iterator pos = - std::find_if( partials.begin(), partials.end(), - PartialUtils::isLabelEqual( refLabel ) ); - if ( pos == partials.end() ) - { - Throw( InvalidArgument, "no Partial has the specified reference label" ); - } - _srcRefPartial = *pos; - } - else - { - _srcRefPartial = Partial(); - } -} - -// --------------------------------------------------------------------------- -// setTargetReferencePartial -// --------------------------------------------------------------------------- -//! Specify the Partial to be used as a reference -//! Partial for the target sequence in a morph of two Partial -//! sequences. The reference partial is used to compute -//! frequencies for very low-amplitude Partials whose frequency -//! estimates are not considered reliable. The reference Partial -//! is considered to have good frequency estimates throughout. -//! The specified Partial must be labeled with its harmonic number. -//! A default (empty) Partial indicates that no reference -//! Partial should be used for the target sequence. -// -void -Morpher::setTargetReferencePartial( const Partial & p ) -{ - if ( p.label() == 0 ) - { - Throw( InvalidArgument, - "the morphing target reference Partial must be " - "labeled with its harmonic number" ); - } - _tgtRefPartial = p; -} - -// --------------------------------------------------------------------------- -// setTargetReferencePartial -// --------------------------------------------------------------------------- -//! Specify the Partial to be used as a reference -//! Partial for the target sequence in a morph of two Partial -//! sequences. The reference partial is used to compute -//! frequencies for very low-amplitude Partials whose frequency -//! estimates are not considered reliable. The reference Partial -//! is considered to have good frequency estimates throughout. -//! A default (empty) Partial indicates that no reference -//! Partial should be used for the target sequence. -//! -//! \param partials a sequence of Partials to search -//! for the reference Partial -//! \param refLabel the label of the Partial in partials -//! that should be selected as the reference -// -void -Morpher::setTargetReferencePartial( const PartialList & partials, - Partial::label_type refLabel ) -{ - if ( refLabel != 0 ) - { - PartialList::const_iterator pos = - std::find_if( partials.begin(), partials.end(), - PartialUtils::isLabelEqual( refLabel ) ); - if ( pos == partials.end() ) - { - Throw( InvalidArgument, "no Partial has the specified reference label" ); - } - _tgtRefPartial = *pos; - } - else - { - _tgtRefPartial = Partial(); - } -} - - -// --------------------------------------------------------------------------- -// amplitudeShape -// --------------------------------------------------------------------------- -// Return the shaping parameter for the amplitude moprhing -// function (only used in new log-amplitude morphing). -// This shaping parameter controls the -// slope of the amplitude morphing function, -// for values greater than 1, this function -// gets nearly linear (like the old amplitude -// morphing function), for values much less -// than 1 (e.g. 1E-5) the slope is gently -// curved and sounds pretty "linear", for -// very small values (e.g. 1E-12) the curve -// is very steep and sounds un-natural because -// of the huge jump from zero amplitude to -// very small amplitude. -double Morpher::amplitudeShape( void ) const -{ - return _logMorphShape; -} - -// --------------------------------------------------------------------------- -// setAmplitudeShape -// --------------------------------------------------------------------------- -// Set the shaping parameter for the amplitude moprhing -// function. This shaping parameter controls the -// slope of the amplitude morphing function, -// for values greater than 1, this function -// gets nearly linear (like the old amplitude -// morphing function), for values much less -// than 1 (e.g. 1E-5) the slope is gently -// curved and sounds pretty "linear", for -// very small values (e.g. 1E-12) the curve -// is very steep and sounds un-natural because -// of the huge jump from zero amplitude to -// very small amplitude. -// -// x is the new shaping parameter, it must be positive. -void Morpher::setAmplitudeShape( double x ) -{ - if ( x <= 0. ) - { - Throw( InvalidArgument, "the amplitude morph shaping parameter must be positive"); - } - _logMorphShape = x; -} - -// --------------------------------------------------------------------------- -// minBreakpointGap -// --------------------------------------------------------------------------- -// Return the minimum time gap (secs) between two Breakpoints -// in the morphed Partials. Morphing two -// Partials can generate a third Partial having -// Breakpoints arbitrarily close together in time, -// and this makes morphs huge. Raising this -// threshold limits the Breakpoint density in -// the morphed Partials. Default is 1/10 ms. -double Morpher::minBreakpointGap( void ) const -{ - return _minBreakpointGapSec; -} - -// --------------------------------------------------------------------------- -// setMinBreakpointGap -// --------------------------------------------------------------------------- -// Set the minimum time gap (secs) between two Breakpoints -// in the morphed Partials. Morphing two -// Partials can generate a third Partial having -// Breakpoints arbitrarily close together in time, -// and this makes morphs huge. Raising this -// threshold limits the Breakpoint density in -// the morphed Partials. Default is 1/10 ms. -// -// x is the new minimum gap in seconds, it must be positive -// -void Morpher::setMinBreakpointGap( double x ) -{ - if ( x <= 0. ) - { - Throw( InvalidArgument, "the minimum Breakpoint gap must be positive"); - } - _minBreakpointGapSec = x; -} - -// -- PartialList access -- - -// --------------------------------------------------------------------------- -// partials -// --------------------------------------------------------------------------- -// Return a reference to this Morpher's list of morphed Partials. -// -PartialList & -Morpher::partials( void ) -{ - return _partials; -} - -// --------------------------------------------------------------------------- -// partials -// --------------------------------------------------------------------------- -// Return a const reference to this Morpher's list of morphed Partials. -// -const PartialList & -Morpher::partials( void ) const -{ - return _partials; -} - -// -- helpers: morphed parameter computation -- - -// --------------------------------------------------------------------------- -// morph_aux -// --------------------------------------------------------------------------- -// Helper function that performs the morph between corresponding pairs -// of Partials identified in a PartialCorrespondence. Called by the -// morph() implementation accepting two sequences of Partials. -// -// PartialCorrespondence represents a map from non-zero Partial -// labels to pairs of Partials (MorphingPair) that should be morphed -// into a single Partial that is assigned that label. -// -void Morpher::morph_aux( PartialCorrespondence & correspondence ) -{ - PartialCorrespondence::const_iterator it; - for ( it = correspondence.begin(); it != correspondence.end(); ++it ) - { - Partial::label_type label = it->first; - MorphingPair match = it->second; - Partial & src = match.src; - Partial & tgt = match.tgt; - - // sanity check: - // one of those Partials must have some Breakpoints - Assert( src.numBreakpoints() != 0 || tgt.numBreakpoints() != 0 ); - - debugger << "morphing " << ( ( 0 < src.numBreakpoints() )?( 1 ):( 0 ) ) - << " and " << ( ( 0 < tgt.numBreakpoints() )?( 1 ):( 0 ) ) - << " partials with label " << label << endl; - - // &^) HEY LOOKIE HERE!!!!!!!!!!!!! - - // ensure that Partials begin and end at zero - // amplitude to solve the problem of Nulls - // getting left out of morphed Partials leading to - // erroneous non-zero amplitude segments: - if ( src.numBreakpoints() != 0 ) - { - if ( src.first().amplitude() != 0.0 && src.startTime() > _minBreakpointGapSec ) - { - double t = src.startTime() - _minBreakpointGapSec; - Breakpoint null = src.parametersAt( t ); - src.insert( t, null ); - } - if ( src.last().amplitude() != 0.0 ) - { - double t = src.endTime() + _minBreakpointGapSec; - Breakpoint null = src.parametersAt( t ); - src.insert( t, null ); - } - } - - if ( tgt.numBreakpoints() != 0 ) - { - if ( tgt.first().amplitude() != 0.0 && tgt.startTime() > _minBreakpointGapSec ) - { - double t = tgt.startTime() - _minBreakpointGapSec; - Breakpoint null = tgt.parametersAt( t ); - tgt.insert( t, null ); - } - if ( tgt.last().amplitude() != 0.0 ) - { - double t = tgt.endTime() + _minBreakpointGapSec; - Breakpoint null = tgt.parametersAt( t ); - tgt.insert( t, null ); - } - } - // &^) HEY LOOKIE HERE!!!!!!!!!!!!! - // the question is: after sticking nulls on the ends, - // should be strip nulls OFF the ends of the morphed - // partial? If so, how many? (ans to second is one, - // cannot have both nulls appear at end of morphed, - // because of min gap). If we unconditionally add - // nulls to ends (regardless of starting and ending - // amps), then we can (I think) be sure that taking - // off one null from each end leaves the Partial in - // an unmolested state.... maybe. No, its possible that - // the morphing function would skip over both artificial - // nulls, so we cannot be sure. Hmmmmm.... - // For now, just leave the nulls on the ends, - // the are relatively harmless. - // - // Actually, a (klugey) solution is to remember the times - // of those artificial nulls, and then see if the - // Partial begins or ends at one of those times. - // No, cannot guarantee that one Partial doesn't - // have a null at the time we put an artificial null - // in the other one. Hmmmmm..... - - - // perform the morph between the two Partials, - // save the result if it has any Breakpoints - // (it may not depending on the morphing functions): - Partial newp = morphPartials( src, tgt, label ); - if ( partial_is_nonnull( newp ) ) - { - _partials.push_back( newp ); - } - } -} - - -// --------------------------------------------------------------------------- -// adjustFrequency -// --------------------------------------------------------------------------- -// Adjust frequency of low-amplitude Breakpoints to be harmonics of the -// reference Partial, if one has been specified. -// -// Leave the phase alone, because I don't know what we can do with it. -// -static void adjustFrequency( Breakpoint & bp, const Partial & ref, - Partial::label_type harmonicNum, - double thresholdDb, - double time ) -{ - if ( ref.numBreakpoints() != 0 ) - { - // compute absolute magnitude thresholds: - static const double FadeRangeDB = 10; - const double BeginFade = std::pow( 10., 0.05 * (thresholdDb+FadeRangeDB) ); - - if ( bp.amplitude() < BeginFade ) - { - const double Threshold = std::pow( 10., 0.05 * thresholdDb ); - const double OneOverFadeSpan = 1. / ( BeginFade - Threshold ); - - double fscale = (double)harmonicNum / ref.label(); - - double alpha = std::min( ( BeginFade - bp.amplitude() ) * OneOverFadeSpan, 1. ); - double fRef = ref.frequencyAt( time ); - bp.setFrequency( ( alpha * ( fRef * fscale ) ) + - ( (1 - alpha) * bp.frequency() ) ); - } - } -} - -// --------------------------------------------------------------------------- -// partial_is_nonnull -// --------------------------------------------------------------------------- -// Helper function to examine a morphed Partial and determine whether -// it has any non-null Breakpoints. If not, there's no point in saving it. -// -static inline bool partial_is_nonnull( const Partial & p ) -{ - for ( Partial::const_iterator it = p.begin(); it != p.end(); ++it ) - { - if ( it.breakpoint().amplitude() != 0.0 ) - { - return true; - } - } - return false; -} - -// --------------------------------------------------------------------------- -// Helper function for performing log-domain interpolation -// (originally was for amplitude only). -// -// alpha == 0 returns x, alpha == 1 returns y -// -// It is essential to add in a small offset, so that -// occasional zero amplitudes do not introduce artifacts -// (if amp is zero, then even if alpha is very small -// the effect is to multiply by zero, because 0^x = 0, -// or note that log(0) is -infinity). -// -// This shaping parameter affects the shape of the morph -// curve only when it is of the same order of magnitude as -// one of the sources (x or y) and the other is much larger. -// -// When shape is very small, the curve representing the -// morphed amplitude is very steep, such that there is a -// huge difference between zero amplitude and very small -// amplitude, and this causes audible artifacts. So instead -// use a larger value that shapes the curve more nicely. -// Just have to subtract this value from the morphed -// amplitude to avoid raising the noise floor a whole lot. -// -static inline double -interpolateLog( double x, double y, double alpha, double shape ) -{ - using std::pow; - - double s = x + shape; - double t = y + shape; - - double v = ( s * pow( t / s, alpha ) ) - shape; - - return v; -} - -// --------------------------------------------------------------------------- -// Helper function for performing linear interpolation -// (used to be the only kind we supported). -// -// alpha == 0 returns x, alpha == 1 returns y -// -static inline double -interpolateLinear( double x, double y, double alpha ) -{ - double v = (x * (1-alpha)) + (y * alpha); - - return v; -} - - -// --------------------------------------------------------------------------- -// Helper function for computing individual morphed amplitude values. -// -inline double -Morpher::interpolateAmplitude( double srcAmp, double tgtAmp, double alpha ) const -{ - double morphedAmp = 0; - - if ( _doLogAmpMorphing ) - { - // if both are small, just return 0 - // HEY, is this really what we want? - static const double Epsilon = 1E-12; - if ( ( srcAmp > Epsilon ) || ( tgtAmp > Epsilon ) ) - { - morphedAmp = interpolateLog( srcAmp, tgtAmp, alpha, _logMorphShape ); - } - } - else - { - morphedAmp = interpolateLinear( srcAmp, tgtAmp, alpha ); - } - - // Partial amplitudes should never be negative - double res = std::max( 0.0, morphedAmp ); - - return res; -} - -// --------------------------------------------------------------------------- -// Helper function for computing individual morphed bandwidth values. -// -inline double -Morpher::interpolateBandwidth( double srcBw, double tgtBw, double alpha ) const -{ - double morphedBw = 0; - - if ( _doLogAmpMorphing ) - { - // if both are small, just return 0 - // HEY, is this really what we want? - static const double Epsilon = 1E-12; - if ( ( srcBw > Epsilon ) || ( tgtBw > Epsilon ) ) - { - morphedBw = interpolateLog( srcBw, tgtBw, alpha, _logMorphShape ); - } - } - else - { - morphedBw = interpolateLinear( srcBw, tgtBw, alpha ); - } - - // Partial bandwidths should never be negative - double res = std::max( 0.0, morphedBw ); - - - return res; -} - -// --------------------------------------------------------------------------- -// Helper function for computing individual morphed frequency values. -// -inline double -Morpher::interpolateFrequency( double srcFreq, double tgtFreq, double alpha ) const -{ - double morphedFreq = 1; - - if ( _doLogFreqMorphing ) - { - // guard against the extremely unlikely possibility that - // one of the frequencies is zero - double shape = 0; - if ( 0 == srcFreq || 0 == tgtFreq ) - { - shape = Morpher::DefaultAmpShape; - } - morphedFreq = interpolateLog( srcFreq, tgtFreq, alpha, shape ); - } - else - { - morphedFreq = interpolateLinear( srcFreq, tgtFreq, alpha ); - } - - return morphedFreq; -} - -// --------------------------------------------------------------------------- -// Helper function for computing individual morphed phase values. -// -inline double -Morpher::interpolatePhase( double srcphase, double tgtphase, double alpha ) const -{ - // Interpolate raw absolute phase values. If the interpolated - // phase matters at all (near the morphing function boudaries 0 - // and 1) then that will give a good target phase value, and the - // frequency will be adjusted to match the phase. Otherwise, - // the phase will just be recomputed to match the interpolated - // frequency. - // - // Wrap the computed phase onto an appropriate range. - // wrap the phases so that they are as similar as possible, - // so that phase interpolation is shift-invariant. - while ( ( srcphase - tgtphase ) > Pi ) - { - srcphase -= 2 * Pi; - } - while ( ( tgtphase - srcphase ) > Pi ) - { - srcphase += 2 * Pi; - } - - double morphedPhase = interpolateLinear( srcphase, tgtphase, alpha ); - - return std::fmod( morphedPhase, 2 * Pi ); -} - -// --------------------------------------------------------------------------- -// Helper function for interpolating Breakpoint parameters -// -inline Breakpoint -Morpher::interpolateParameters( const Breakpoint & srcBkpt, const Breakpoint & tgtBkpt, - double fweight, double aweight, double bweight ) const -{ - Breakpoint morphed; - - // interpolate frequencies: - morphed.setFrequency( - interpolateFrequency( srcBkpt.frequency(), tgtBkpt.frequency(), - fweight ) ); - - // interpolate LOG amplitudes: - morphed.setAmplitude( - interpolateAmplitude( srcBkpt.amplitude(), tgtBkpt.amplitude(), - aweight ) ); - - // interpolate bandwidth: - morphed.setBandwidth( - interpolateBandwidth( srcBkpt.bandwidth(), tgtBkpt.bandwidth(), - bweight ) ); - - // interpolate phase: - morphed.setPhase( - interpolatePhase( srcBkpt.phase(), tgtBkpt.phase(), fweight ) ); - - return morphed; -} - -// --------------------------------------------------------------------------- -// appendMorphedSrc -// --------------------------------------------------------------------------- -//! Compute morphed parameter values at the specified time, using -//! the source Breakpoint (assumed to correspond exactly to the -//! specified time) and the target Partial (whose parameters are -//! examined at the specified time). Append the morphed Breakpoint -//! to newp only if the source should contribute to the morph at -//! the specified time. -//! -//! If the target Partial is a dummy Partial (no Breakpoints), fade the -//! source instead of morphing. -//! -//! \param srcBkpt is the Breakpoint corresponding to a morph function -//! value of 0. -//! \param tgtPartial is the Partial corresponding to a morph function -//! value of 1, evaluated at the specified time. -//! \param time is the time corresponding to srcBkpt (used -//! to evaluate the morphing functions and tgtPartial). -//! \param newp is the morphed Partial under construction, the morphed -//! Breakpoint is added to this Partial. -// -void -Morpher::appendMorphedSrc( Breakpoint srcBkpt, const Partial & tgtPartial, - double time, Partial & newp ) -{ - double fweight = _freqFunction->valueAt( time ); - double aweight = _ampFunction->valueAt( time ); - double bweight = _bwFunction->valueAt( time ); - - // Need to insert a null (0 amplitude) Breakpoint - // if src and tgt are 0 amplitude but the morphed - // Partial is not. In rare cases, it is possible - // to miss a needed null if we don't check for it - // explicitly. - bool needNull = ( newp.numBreakpoints() != 0 ) && - ( newp.last().amplitude() != 0 ) && - ( srcBkpt.amplitude() == 0) && - ( tgtPartial.numBreakpoints() != 0 ) && - ( tgtPartial.amplitudeAt( time ) == 0 ); - - // Don't insert Breakpoints at src times if all - // morph functions equal 1 (or > MaxMorphParam), - // and a null is not needed. - const double MaxMorphParam = .9; - if ( fweight < MaxMorphParam || - aweight < MaxMorphParam || - bweight < MaxMorphParam || - needNull ) - { - - // adjust source Breakpoint frequencies according to the reference - // Partial (if a reference has been specified): - adjustFrequency( srcBkpt, _srcRefPartial, newp.label(), _freqFixThresholdDb, time ); - - if ( 0 == tgtPartial.numBreakpoints() ) - { - // no corresponding target Partial exists: - if ( 0 == _tgtRefPartial.numBreakpoints() ) - { - // no reference Partial specified for tgt, - // fade src instead: - newp.insert( time, fadeSrcBreakpoint( srcBkpt, time ) ); - } - else - { - // reference Partial has been provided for tgt, - // use it to construct a fake Breakpoint to morph - // with the src: - Breakpoint tgtBkpt = _tgtRefPartial.parametersAt( time ); - double fscale = (double) newp.label() / _tgtRefPartial.label(); - tgtBkpt.setFrequency( fscale * tgtBkpt.frequency() ); - tgtBkpt.setPhase( fscale * tgtBkpt.phase() ); - tgtBkpt.setAmplitude( 0 ); - tgtBkpt.setBandwidth( 0 ); - - // compute interpolated Breakpoint parameters: - newp.insert( time, interpolateParameters( srcBkpt, tgtBkpt, fweight, - aweight, bweight ) ); - } - } - else - { - Breakpoint tgtBkpt = tgtPartial.parametersAt( time ); - - // adjust target Breakpoint frequencies according to the reference - // Partial (if a reference has been specified): - adjustFrequency( tgtBkpt, _tgtRefPartial, newp.label(), _freqFixThresholdDb, time ); - - // compute interpolated Breakpoint parameters: - Breakpoint morphed = interpolateParameters( srcBkpt, tgtBkpt, fweight, - aweight, bweight ); - newp.insert( time, morphed ); - } - } -} - -// --------------------------------------------------------------------------- -// appendMorphedTgt -// --------------------------------------------------------------------------- -//! Compute morphed parameter values at the specified time, using -//! the target Breakpoint (assumed to correspond exactly to the -//! specified time) and the source Partial (whose parameters are -//! examined at the specified time). Append the morphed Breakpoint -//! to newp only if the target should contribute to the morph at -//! the specified time. -//! -//! If the source Partial is a dummy Partial (no Breakpoints), fade the -//! target instead of morphing. -//! -//! \param tgtBkpt is the Breakpoint corresponding to a morph function -//! value of 1. -//! \param srcPartial is the Partial corresponding to a morph function -//! value of 0, evaluated at the specified time. -//! \param time is the time corresponding to srcBkpt (used -//! to evaluate the morphing functions and srcPartial). -//! \param newp is the morphed Partial under construction, the morphed -//! Breakpoint is added to this Partial. -// -void -Morpher::appendMorphedTgt( Breakpoint tgtBkpt, const Partial & srcPartial, - double time, Partial & newp ) -{ - double fweight = _freqFunction->valueAt( time ); - double aweight = _ampFunction->valueAt( time ); - double bweight = _bwFunction->valueAt( time ); - - // Need to insert a null (0 amplitude) Breakpoint - // if src and tgt are 0 amplitude but the morphed - // Partial is not. In rare cases, it is possible - // to miss a needed null if we don't check for it - // explicitly. - bool needNull = ( newp.numBreakpoints() != 0 ) && - ( newp.last().amplitude() != 0 ) && - ( tgtBkpt.amplitude() == 0) && - ( srcPartial.numBreakpoints() != 0 ) && - ( srcPartial.amplitudeAt( time ) == 0 ); - - // Don't insert Breakpoints at src times if all - // morph functions equal 0 (or < MinMorphParam), - // and a null is not needed. - const double MinMorphParam = .1; - if ( fweight > MinMorphParam || - aweight > MinMorphParam || - bweight > MinMorphParam || - needNull ) - { - - // adjust target Breakpoint frequencies according to the reference - // Partial (if a reference has been specified): - adjustFrequency( tgtBkpt, _tgtRefPartial, newp.label(), _freqFixThresholdDb, time ); - - if ( 0 == srcPartial.numBreakpoints() ) - { - // no corresponding source Partial exists: - if ( 0 == _srcRefPartial.numBreakpoints() ) - { - // no reference Partial specified for src, - // fade tgt instead: - newp.insert( time, fadeTgtBreakpoint( tgtBkpt, time ) ); - } - else - { - // reference Partial has been provided for src, - // use it to construct a fake Breakpoint to morph - // with the tgt: - Breakpoint srcBkpt = _srcRefPartial.parametersAt( time ); - double fscale = (double) newp.label() / _srcRefPartial.label(); - srcBkpt.setFrequency( fscale * srcBkpt.frequency() ); - srcBkpt.setPhase( fscale * srcBkpt.phase() ); - srcBkpt.setAmplitude( 0 ); - srcBkpt.setBandwidth( 0 ); - - // compute interpolated Breakpoint parameters: - newp.insert( time, interpolateParameters( srcBkpt, tgtBkpt, fweight, - aweight, bweight ) ); - } - } - else - { - Breakpoint srcBkpt = srcPartial.parametersAt( time ); - - // adjust source Breakpoint frequencies according to the reference - // Partial (if a reference has been specified): - adjustFrequency( srcBkpt, _srcRefPartial, newp.label(), _freqFixThresholdDb, time ); - - // compute interpolated Breakpoint parameters: - Breakpoint morphed = interpolateParameters( srcBkpt, tgtBkpt, fweight, - aweight, bweight ); - newp.insert( time, morphed ); - } - } -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Morpher.h b/loris_library/Source/src/Morpher.h deleted file mode 100644 index a291cac..0000000 --- a/loris_library/Source/src/Morpher.h +++ /dev/null @@ -1,590 +0,0 @@ -#ifndef INCLUDE_MORPHER_H -#define INCLUDE_MORPHER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Morpher.h - * - * Definition of class Morpher. - * - * Kelly Fitz, 15 Oct 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "PartialList.h" -#include "Partial.h" - -#include // for auto_ptr - -// begin namespace -namespace Loris { - -class Envelope; - -// --------------------------------------------------------------------------- -// Class Morpher -// -//! Class Morpher performs sound morphing and Partial parameter -//! envelope interpolation according to a trio of frequency, amplitude, -//! and bandwidth morphing functions, described by Envelopes. -//! Sound morphing is achieved by interpolating the time-varying -//! frequencies, amplitudes, and bandwidths of corresponding partials -//! obtained from reassigned bandwidth-enhanced analysis of the source -//! and target sounds. Partial correspondences may be established by -//! labeling, using instances of the Channelizer and Distiller classes. -//! -//! The Morpher collects morphed Partials in a PartialList, that is -//! accessible to clients. -//! -//! For more information about sound morphing using -//! the Reassigned Bandwidth-Enhanced Additive Sound -//! Model, refer to the Loris website: -//! www.cerlsoundgroup.org/Loris/. -//! -//! Morpher is a leaf class, do not subclass. -// -class Morpher -{ -// -- instance variables -- - - std::auto_ptr< Envelope > _freqFunction; //! frequency morphing function - std::auto_ptr< Envelope > _ampFunction; //! amplitude morphing function - std::auto_ptr< Envelope > _bwFunction; //! bandwidth morphing function - - PartialList _partials; //! collect Partials here - - Partial _srcRefPartial; //! reference Partials - Partial _tgtRefPartial; //! for source and target sounds when - //! morphing sequences of labeled Partials, - //! default (empty Partial) implies no - //! reference Partial is used - - double _freqFixThresholdDb; //! amplitude threshold below which Partial - //! frequencies are corrected according to - //! a reference Partial, if specified. - - double _logMorphShape; //! shaping parameter that controls the - //! shape of the logarithmic morphing function, - //! mostly when one of the source values - //! is equal to zero. - //! Only relevant when _doLogAmpMorphing is true. - //! - //! Don't use this for anything, just leave it - //! at the default. - - double _minBreakpointGapSec; //! the minimum time gap between two Breakpoints - //! in the morphed Partials. Morphing two - //! Partials can generate a third Partial having - //! Breakpoints arbitrarily close together in time, - //! and this makes morphs huge. Raising this - //! threshold limits the Breakpoint density in - //! the morphed Partials. - //! Default is 1/10 ms. - - - bool _doLogAmpMorphing; //! if true (default), amplitudes and bandwidths - //! are morphed in the log domain, if false they - //! are morphed in the linear domain. - - bool _doLogFreqMorphing; //! if true, frequencies are morphed in the log - //! domain, if false (default) they are morphed - //! in the linear domain. - - -// -- public interface -- -public: -// -- construction -- - - //! Construct a new Morpher using the same morphing envelope for - //! frequency, amplitude, and bandwidth (noisiness). - //! - //! \param f is the Envelope to clone for all three morphing - //! functions. - Morpher( const Envelope & f ); - - //! Construct a new Morpher using the specified morphing envelopes for - //! frequency, amplitude, and bandwidth (noisiness). - //! - //! \param ff is the Envelope to clone for the frequency morphing function - //! \param af is the Envelope to clone for the amplitude morphing function - //! \param bwf is the Envelope to clone for the bandwidth morphing function - Morpher( const Envelope & ff, const Envelope & af, const Envelope & bwf ); - - //! Construct a new Morpher that is a duplicate of rhs. - //! - //! \param rhs is the Morpher to duplicate - Morpher( const Morpher & rhs ); - - //! Destroy this Morpher. - ~Morpher( void ); - - //! Make this Morpher a duplicate of rhs. - //! - //! \param rhs is the Morpher to duplicate - Morpher & operator= ( const Morpher & rhs ); - -// -- morphed parameter computation -- - -// -- Partial morphing -- - - //! Morph a pair of Partials to yield a new morphed Partial. - //! Dummy Partials (having no Breakpoints) don't contribute to the - //! morph, except to cause their opposite to fade out. - //! Either (or neither) the source or target Partial may be a dummy - //! Partial (no Breakpoints), but not both. The morphed - //! Partial has Breakpoints at times corresponding to every Breakpoint - //! in both source Partials, omitting Breakpoints that would be - //! closer than the minBreakpointGap to their predecessor. - //! The new morphed Partial is assigned the specified label and returned. - //! - //! \param src is the Partial corresponding to a morph function - //! value of 0, evaluated at the specified time. - //! \param tgt is the Partial corresponding to a morph function - //! value of 1, evaluated at the specified time. - //! \param assignLabel is the label assigned to the morphed Partial - //! \return the morphed Partial - Partial morphPartials( Partial src, Partial tgt, int assignLabel ); - - //! Bad legacy name for morphPartials. - //! \deprecated Use morphPartials instead. - Partial morphPartial( Partial src, Partial tgt, int assignLabel ) - { return morphPartials( src, tgt, assignLabel ); } - - //! Morph two sounds (collections of Partials labeled to indicate - //! correspondences) into a single labeled collection of Partials. - //! Unlabeled Partials (having label 0) are crossfaded. The morphed - //! and crossfaded Partials are stored in the Morpher's PartialList. - //! - //! The Partials in the first range are treated as components of the - //! source sound, corresponding to a morph function value of 0, and - //! those in the second are treated as components of the target sound, - //! corresponding to a morph function value of 1. - //! - //! \sa crossfade, morphPartials - //! - //! \param beginSrc is the beginning of the sequence of Partials - //! corresponding to a morph function value of 0. - //! \param endSrc is (one past) the end of the sequence of Partials - //! corresponding to a morph function value of 0. - //! \param beginTgt is the beginning of the sequence of Partials - //! corresponding to a morph function value of 1. - //! \param endTgt is (one past) the end of the sequence of Partials - //! corresponding to a morph function value of 1. - void morph( PartialList::const_iterator beginSrc, - PartialList::const_iterator endSrc, - PartialList::const_iterator beginTgt, - PartialList::const_iterator endTgt ); - - //! Crossfade Partials with no correspondences. - //! - //! Unlabeled Partials (having the specified label) are considered to - //! have no correspondences, so they are just faded out, and not - //! actually morphed. Consistent with the morphing behavior, - //! crossfaded Partials are thinned, if necssary, so that no - //! two Breakpoints are closer in time than the minBreakpointGap. - //! - //! The Partials in the first range are treated as components of the - //! source sound, corresponding to a morph function value of 0, and - //! those in the second are treated as components of the target sound, - //! corresponding to a morph function value of 1. - //! - //! The crossfaded Partials are stored in the Morpher's PartialList. - //! - //! \param beginSrc is the beginning of the sequence of Partials - //! corresponding to a morph function value of 0. - //! \param endSrc is (one past) the end of the sequence of Partials - //! corresponding to a morph function value of 0. - //! \param beginTgt is the beginning of the sequence of Partials - //! corresponding to a morph function value of 1. - //! \param endTgt is (one past) the end of the sequence of Partials - //! corresponding to a morph function value of 1. - //! \param label is the label to associate with unlabeled - //! Partials (default is 0). - void crossfade( PartialList::const_iterator beginSrc, - PartialList::const_iterator endSrc, - PartialList::const_iterator beginTgt, - PartialList::const_iterator endTgt, - Partial::label_type label = 0 ); - - - //! Compute morphed parameter values at the specified time, using - //! the source and target Breakpoints (assumed to correspond exactly - //! to the specified time). - //! - //! \param srcBkpt is the Breakpoint corresponding to a morph function - //! value of 0. - //! \param tgtBkpt is the Breakpoint corresponding to a morph function - //! value of 1. - //! \param time is the time corresponding to srcBkpt (used - //! to evaluate the morphing functions and tgtPartial). - //! \return the morphed Breakpoint - // - Breakpoint - morphBreakpoints( Breakpoint srcBkpt, Breakpoint tgtBkpt, - double time ) const; - - //! Compute morphed parameter values at the specified time, using - //! the source Breakpoint (assumed to correspond exactly to the - //! specified time) and the target Partial (whose parameters are - //! examined at the specified time). - //! - //! DEPRECATED do not use. - //! - //! \pre the target Partial may not be a dummy Partial (no Breakpoints). - //! - //! \param bp is the Breakpoint corresponding to a morph function - //! value of 0. - //! \param tgtPartial is the Partial corresponding to a morph function - //! value of 1, evaluated at the specified time. - //! \param time is the time corresponding to srcBkpt (used - //! to evaluate the morphing functions and tgtPartial). - //! \return the morphed Breakpoint - Breakpoint - morphSrcBreakpoint( const Breakpoint & bp, const Partial & tgtPartial, - double time ) const; - - //! Compute morphed parameter values at the specified time, using - //! the target Breakpoint (assumed to correspond exactly to the - //! specified time) and the source Partial (whose parameters are - //! examined at the specified time). - //! - //! DEPRECATED do not use. - //! - //! \pre the source Partial may not be a dummy Partial (no Breakpoints). - //! - //! \param bp is the Breakpoint corresponding to a morph function - //! value of 1. - //! \param srcPartial is the Partial corresponding to a morph function - //! value of 0, evaluated at the specified time. - //! \param time is the time corresponding to srcBkpt (used - //! to evaluate the morphing functions and tgtPartial). - //! \return the morphed Breakpoint - Breakpoint - morphTgtBreakpoint( const Breakpoint & bp, const Partial & srcPartial, - double time ) const; - - //! Compute morphed parameter values at the specified time, using - //! the source Breakpoint, assumed to correspond exactly to the - //! specified time, and assuming that there is no corresponding - //! target Partial, so the source Breakpoint should be simply faded. - //! - //! \param bp is the Breakpoint corresponding to a morph function - //! value of 0. - //! \param time is the time corresponding to bp (used - //! to evaluate the morphing functions). - //! \return the faded Breakpoint - Breakpoint fadeSrcBreakpoint( Breakpoint bp, double time ) const; - - //! Compute morphed parameter values at the specified time, using - //! the target Breakpoint, assumed to correspond exactly to the - //! specified time, and assuming that there is not corresponding - //! source Partial, so the target Breakpoint should be simply faded. - //! - //! \param bp is the Breakpoint corresponding to a morph function - //! value of 1. - //! \param time is the time corresponding to bp (used - //! to evaluate the morphing functions). - //! \return the faded Breakpoint - Breakpoint fadeTgtBreakpoint( Breakpoint bp, double time ) const; - -// -- morphing function access/mutation -- - - //! Assign a new frequency morphing envelope to this Morpher. - void setFrequencyFunction( const Envelope & f ); - - //! Assign a new amplitude morphing envelope to this Morpher. - void setAmplitudeFunction( const Envelope & f ); - - //! Assign a new bandwidth morphing envelope to this Morpher. - void setBandwidthFunction( const Envelope & f ); - - //! Return a reference to this Morpher's frequency morphing envelope. - const Envelope & frequencyFunction( void ) const; - - //! Return a reference to this Morpher's amplitude morphing envelope. - const Envelope & amplitudeFunction( void ) const; - - //! Return a reference to this Morpher's bandwidth morphing envelope. - const Envelope & bandwidthFunction( void ) const; - - //! Return the shaping parameter for the amplitude moprhing - //! function (only used in log-amplitude morphing). - //! - //! DEPRECATED - double amplitudeShape( void ) const; - - //! Set the shaping parameter for the amplitude moprhing - //! function (only used in log-amplitude morphing). - //! Only relevant when _doLogAmpMorphing is true. - //! Don't use this for anything, just leave it - //! at the default. - //! - //! DEPRECATED - void setAmplitudeShape( double x ); - - //! Enable (or disable) log-domain amplitude and bandwidth morphing. - //! Default is true. - void enableLogAmpMorphing( bool enable = true ) { _doLogAmpMorphing = enable; } - - //! Enable (or disable) log-domain frequency morphing. - //! Default is false. - void enableLogFreqMorphing( bool enable = true ) { _doLogFreqMorphing = enable; } - - - //! Return the minimum time gap (secs) between two Breakpoints - //! in the morphed Partials. Morphing two - //! Partials can generate a third Partial having - //! Breakpoints arbitrarily close together in time, - //! and this makes morphs huge. Raising this - //! threshold limits the Breakpoint density in - //! the morphed Partials. Default is 1/10 ms. - double minBreakpointGap( void ) const; - - //! Set the minimum time gap (secs) between two Breakpoints - //! in the morphed Partials. Morphing two - //! Partials can generate a third Partial having - //! Breakpoints arbitrarily close together in time, - //! and this makes morphs huge. Raising this - //! threshold limits the Breakpoint density in - //! the morphed Partials. Default is 1/10 ms. - //! - //! \param x is the new minimum gap in seconds, it must be - //! positive - //! \throw InvalidArgument if the specified gap is not positive - void setMinBreakpointGap( double x ); - - -// -- reference Partial label access/mutation -- - - //! Return the Partial to be used as a reference - //! Partial for the source sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference Partial - //! should be used for the source sequence. - const Partial & sourceReferencePartial( void ) const; - - //! Return the Partial to be used as a reference - //! Partial for the source sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference Partial - //! should be used for the source sequence. - Partial & sourceReferencePartial( void ); - - //! Return the Partial to be used as a reference - //! Partial for the target sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference Partial - //! should be used for the target sequence. - const Partial & targetReferencePartial( void ) const; - - //! Return the Partial to be used as a reference - //! Partial for the target sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference Partial - //! should be used for the target sequence. - Partial & targetReferencePartial( void ); - - //! Specify the Partial to be used as a reference - //! Partial for the source sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! The specified Partial must be labeled with its harmonic number. - //! A default (empty) Partial indicates that no reference - //! Partial should be used for the source sequence. - void setSourceReferencePartial( const Partial & p = Partial() ); - - //! Specify the Partial to be used as a reference - //! Partial for the source sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference - //! Partial should be used for the source sequence. - //! - //! \param partials a sequence of Partials to search - //! for the reference Partial - //! \param refLabel the label of the Partial in partials - //! that should be selected as the reference - void setSourceReferencePartial( const PartialList & partials, - Partial::label_type refLabel ); - - //! Specify the Partial to be used as a reference - //! Partial for the target sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! The specified Partial must be labeled with its harmonic number. - //! A default (empty) Partial indicates that no reference - //! Partial should be used for the target sequence. - void setTargetReferencePartial( const Partial & p = Partial() ); - - //! Specify the Partial to be used as a reference - //! Partial for the target sequence in a morph of two Partial - //! sequences. The reference partial is used to compute - //! frequencies for very low-amplitude Partials whose frequency - //! estimates are not considered reliable. The reference Partial - //! is considered to have good frequency estimates throughout. - //! A default (empty) Partial indicates that no reference - //! Partial should be used for the target sequence. - //! - //! \param partials a sequence of Partials to search - //! for the reference Partial - //! \param refLabel the label of the Partial in partials - //! that should be selected as the reference - void setTargetReferencePartial( const PartialList & partials, - Partial::label_type refLabel ); - -// -- PartialList access -- - - //! Return a reference to this Morpher's list of morphed Partials. - PartialList & partials( void ); - - //! Return a const reference to this Morpher's list of morphed Partials. - const PartialList & partials( void ) const; - -// -- global morphing defaults and constants -- - - //! Amplitude threshold (dB) below which - //! Partial frequencies are corrected using - //! the reference Partial frequency envelope - //! (if specified). - static const double DefaultFixThreshold; - - //! Default amplitude shaping parameter, used in - //! interpolateLogAmplitudes to perform logarithmic - //! amplitude morphs. - //! - //! Compile Loris with LINEAR_AMP_MORPHS defined for - //! legacy-style linear amplitude morphs by default. - //! - //! Change from default using setAmplitudeShape. - static const double DefaultAmpShape; - - //! Default minimum time (sec) between Breakpoints in - //! morphed Partials. - //! Change from default using setMinBreakpointGap. - static const double DefaultBreakpointGap; - -private: - -// -- helper -- - - // PartialCorrespondence represents a map from non-zero Partial - // labels to pairs of pointers to Partials that should be morphed - // into a single Partial that is assigned that label. - // MorphingPair is a pair of pointers to Partials that are - // initialized to zero, and it is the element type for the - // PartialCorrespondence map. - struct MorphingPair - { - Partial src; - Partial tgt; - }; - typedef std::map< Partial::label_type, MorphingPair > PartialCorrespondence; - - //! Helper function that performs the morph between corresponding pairs - //! of Partials identified in a PartialCorrespondence. Called by the - //! morph() implementation accepting two sequences of Partials. - void morph_aux( PartialCorrespondence & correspondence ); - - //! Compute morphed parameter values at the specified time, using - //! the source Breakpoint (assumed to correspond exactly to the - //! specified time) and the target Partial (whose parameters are - //! examined at the specified time). Append the morphed Breakpoint - //! to newp only if the target should contribute to the morph at - //! the specified time. - //! - //! \pre the target Partial may not be a dummy Partial (no Breakpoints). - //! - //! \param srcBkpt is the Breakpoint corresponding to a morph function - //! value of 0. - //! \param tgtPartial is the Partial corresponding to a morph function - //! value of 1, evaluated at the specified time. - //! \param time is the time corresponding to srcBkpt (used - //! to evaluate the morphing functions and tgtPartial). - //! \param newp is the morphed Partial under construction, the morphed - //! Breakpoint is added to this Partial. - // - void appendMorphedSrc( Breakpoint srcBkpt, const Partial & tgtPartial, - double time, Partial & newp ); - - //! Compute morphed parameter values at the specified time, using - //! the target Breakpoint (assumed to correspond exactly to the - //! specified time) and the source Partial (whose parameters are - //! examined at the specified time). Append the morphed Breakpoint - //! to newp only if the target should contribute to the morph at - //! the specified time. - //! - //! \pre the source Partial may not be a dummy Partial (no Breakpoints). - //! - //! \param tgtBkpt is the Breakpoint corresponding to a morph function - //! value of 1. - //! \param srcPartial is the Partial corresponding to a morph function - //! value of 0, evaluated at the specified time. - //! \param time is the time corresponding to srcBkpt (used - //! to evaluate the morphing functions and srcPartial). - //! \param newp is the morphed Partial under construction, the morphed - //! Breakpoint is added to this Partial. - // - void appendMorphedTgt( Breakpoint tgtBkpt, const Partial & srcPartial, - double time, Partial & newp ); - - - //! Parameterinterpolation helpers. - Breakpoint - interpolateParameters( const Breakpoint & srcBkpt, const Breakpoint & tgtBkpt, - double fweight, double aweight, double bweight ) const; - - double interpolateAmplitude( double srcAmp, double tgtAmp, double alpha ) const; - double interpolateBandwidth( double srcBw, double tgtBw, double alpha ) const; - double interpolateFrequency( double srcFreq, double tgtFreq, double alpha ) const; - double interpolatePhase( double srcphase, double tgtphase, double alpha ) const; - - - // Recompute phases for a morphed Partial, so that the synthesized phases - // match the source phases as closesly as possible at times when the - // frequency morphing function is equal to 0 or 1. - void fixMorphedPhases( Partial & newp ) const; - -}; // end of class Morpher - -} // end of namespace Loris - -#endif /* ndef INCLUDE_MORPHER_H */ diff --git a/loris_library/Source/src/NoiseGenerator.cpp b/loris_library/Source/src/NoiseGenerator.cpp deleted file mode 100644 index c1c7c0e..0000000 --- a/loris_library/Source/src/NoiseGenerator.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * NoiseGenerator.C - * - * Implementation of a class representing a gaussian noise generator, filtered and - * used as a modulator in bandwidth-enhanced synthesis. - * - * Kelly Fitz, 5 June 2003 - * revised 11 October 2009 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "NoiseGenerator.h" -#include -#include - - -// begin namespace -namespace Loris { - -// --- construction --- - -// --------------------------------------------------------------------------- -// (default) constructor -// --------------------------------------------------------------------------- -//! Create a new noise generator with the (optionally) specified -//! seed (default is 1.0). -//! -//! \param initSeed is the initial seed for the random number generator -// -NoiseGenerator::NoiseGenerator( double initSeed ) : - m_useed( initSeed ), - m_gset( 0 ), - m_iset( false ) -{ -} - -// --------------------------------------------------------------------------- -// seed -// --------------------------------------------------------------------------- -//! Re-seed the random number generator. -//! -//! \param newSeed is the new seed for the random number generator -// -void -NoiseGenerator::seed( double newSeed ) -{ - m_useed = newSeed; -} - -// --- random number generation --- - -// --------------------------------------------------------------------------- -// uniform random number generator -// --------------------------------------------------------------------------- -// Taken from "Random Number Generators: Good Ones Are Hard To Find," -// Stephen Park and Keith Miller, Communications of the ACM, October 1988, -// vol. 31, Number 10. -// -// This version will work as long as floating point values are represented -// with at least a 46 bit mantissa. The IEEE standard 64 bit floating point -// format has a 53 bit mantissa. -// -// The correctness of the implementation can be checked by confirming that -// after 10000 iterations, the seed, initialized to 1, is 1043618065. -// I have confirmed this. -// -// I have also confirmed that it still works (is correct after 10000 -// iterations) when I replace the divides with multiplies by oneOverM. -// -// Returns a uniformly distributed random double on the range [0., 1.). -// -// -kel 7 Nov 1997. -// -// trunc() is a problem. It's not in cmath, officially, though -// Metrowerks has it in there. SGI has it in math.h which is -// (erroneously!) included in g++ cmath, but trunc is not imported -// into std. For these two compilers, could just import std. But -// trnc doesn't seem to exist anywhere in Linux g++, so use std::modf(). -// DON'T use integer conversion, because long int ins't as long -// as double's mantissa! -// -static inline double trunc( double x ) { double y; std::modf(x, &y); return y; } - -inline double -NoiseGenerator::uniform( void ) -{ - static const double a = 16807.L; - static const double m = 2147483647.L; // == LONG_MAX - static const double oneOverM = 1.L / m; - - double temp = a * m_useed; - m_useed = temp - m * trunc( temp * oneOverM ); - return m_useed * oneOverM; -} - -// --------------------------------------------------------------------------- -// gaussian_normal -// --------------------------------------------------------------------------- -// Approximate the normal distribution using the Box-Muller transformation. -// This is a better approximation and faster algorithm than the 12 u.v. sum. -// -// This is slightly different than the thing I got off the web, I (have to) -// assume (for now) that I knew what I was doing when I altered it. -// -inline double -NoiseGenerator::gaussian_normal( void ) -{ - //static int m_iset = 0; // boolean really, now member variables - //static double m_gset; - - double r = 1., fac, v1, v2; - - if ( ! m_iset ) - { - v1 = 2. * uniform() - 1.; - v2 = 2. * uniform() - 1.; - r = v1*v1 + v2*v2; - while( r >= 1. ) - { - // v1 = 2. * uniform() - 1.; - v1 = v2; - v2 = 2. * uniform() - 1.; - r = v1*v1 + v2*v2; - } - - fac = std::sqrt( -2. * std::log(r) / r ); - m_gset = v1 * fac; - m_iset = true; - return v2 * fac; - } - else - { - m_iset = false; - return m_gset; - } -} - -// --- sample generation --- - -// --------------------------------------------------------------------------- -// sample -// --------------------------------------------------------------------------- -//! Generate and return a new sample of Gaussian noise having zero -//! mean and unity standard deviation. Approximate the normal distribution -//! using the Box-Muller transformation applied to a uniform random number -//! generator taken from "Random Number Generators: Good Ones Are Hard To Find," -//! Stephen Park and Keith Miller, Communications of the ACM, October 1988, -//! vol. 31, Number 10. -// -double -NoiseGenerator::sample( void ) -{ - double sample = gaussian_normal(); - return sample; -} - - -} // end of namespace Loris diff --git a/loris_library/Source/src/NoiseGenerator.h b/loris_library/Source/src/NoiseGenerator.h deleted file mode 100644 index 95ddccd..0000000 --- a/loris_library/Source/src/NoiseGenerator.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef NOISEGENERATOR_H -#define NOISEGENERATOR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * NoiseGenerator.h - * - * Definition of a class representing a gaussian noise generator, filtered and - * used as a modulator in bandwidth-enhanced synthesis. - * - * Kelly Fitz, 5 June 2003 - * revised 11 October 2009 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class NoiseGenerator -// -class NoiseGenerator -{ -// --- interface --- - -public: - - //! Create a new noise generator with the (optionally) specified - //! seed (default is 1.0). - //! - //! \param initSeed is the initial seed for the random number generator - explicit NoiseGenerator( double initSeed = 1.0 ); - - - // copy and assign are free - - - //! Re-seed the random number generator. - //! - //! \param newSeed is the new seed for the random number generator - void seed( double newSeed ); - - // sample - // - //! Generate and return a new sample of Gaussian noise having zero - //! mean and unity standard deviation. Approximate the normal distribution - //! using the Box-Muller transformation applied to a uniform random number - //! generator taken from "Random Number Generators: Good Ones Are Hard To Find," - //! Stephen Park and Keith Miller, Communications of the ACM, October 1988, - //! vol. 31, Number 10. - double sample( void ); - - //! Function call operator, same as calling sample(). - //! - //! \sa sample - double operator() ( void ) { return sample(); } - - -// --- implementation --- -private: - - // random number generation helpers - inline double uniform( void ); - inline double gaussian_normal( void ); - - - // random number generator state variables - double m_useed; - double m_gset; - bool m_iset; - -}; - - -} // end of namespace Loris - -#endif /* ndef NOISEGENERATOR_H */ diff --git a/loris_library/Source/src/Notifier.cpp b/loris_library/Source/src/Notifier.cpp deleted file mode 100644 index 8c05a0d..0000000 --- a/loris_library/Source/src/Notifier.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Notifier.C - * - * Definitions of the ostreams used for notification throughout the Loris - * library (notifier and debugger), and the c-linkable functions for assigning - * notification handlers (of type NotificationHandler, see Notifier.h) - * to each. - * - * These ostreams use a streambuf derivative, NotifierBuf, to buffer characters - * in a std::string, and post them (via a handler) when a newline is received. - * NotifierBuf is defined and implemented below. - * - * Kelly Fitz, 28 Feb 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Notifier.h" -#include -#include - -#if defined(__GNUC__) - // other compilers have this problem? - typedef int int_type; -#endif - -using namespace std; - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// defaultNotifierhandler -// --------------------------------------------------------------------------- -// By default, notifications go to stdout (no need to bring in iostreams -// for this. -// -// Is printf different from fprint to stdout? On the mac, using CW5, and -// linking into a Python module (main() written in c), only printf works. -// -static void defaultNotifierhandler( const char * s ) -{ - //cout << s << endl; - //fprintf( stdout, "%s\n", s ); - printf( "%s\n", s ); -} - -// --------------------------------------------------------------------------- -// class NotifierBuf -// -// streambuf derivative that buffers output in a std::string -// and posts it to a handler (_post) when a newline is received. -// -class NotifierBuf : public streambuf -{ -// -- public interface -- -public: -// construction: - NotifierBuf( const std::string & s = "" ) : - _str(s), _post( defaultNotifierhandler ) - // confirm construction: - // { printf( "created a NotifierBuf.\n" ); } - {} - -// virtual destructor so NotifierBuf can be subclassed: -// (use compiler generated, streambuf has virtual destructor) - //virtual ~NotifierBuf( void ); - -// handler manipulation: - NotificationHandler setHandler( NotificationHandler h ) throw() - { - NotificationHandler prev = _post; - _post = h; - return prev; - } - -protected: - // called every time a character is written: - virtual int_type overflow( int_type c ) - { - if ( c == '\n' ) { - _post( _str.c_str() ); - _str = ""; - } - else if ( c != EOF ) { - char ch(c); - _str += ch; - //_str += static_cast(c); ??? - } - return c; - } - -private: - // buffer characters in a string: - std::string _str; - - // handler: - NotificationHandler _post; - -}; // end of class NotifierBuf - -// --------------------------------------------------------------------------- -// stream instances -// --------------------------------------------------------------------------- -// ostreams used throughout Loris for notification. -// -// Instead of making these globals by declaring them at file scope, -// make them static to these initializer functions, to make sure (?) -// that their constructors get called. -// -static NotifierBuf & notifierBuffer(void) -{ - static NotifierBuf buf; - return buf; -} - -std::ostream & getNotifierStream(void) -{ - static ostream os(¬ifierBuffer()); - return os; -} - - -#if defined( Debug_Loris ) - static NotifierBuf & debuggerBuffer(void) - { - static NotifierBuf buf; - return buf; - } -#else - // to do nothing at all, need a dummy streambuf: - struct Dummybuf : public streambuf - { - }; - static Dummybuf & debuggerBuffer( void ) - { - static Dummybuf buf; - return buf; - } -#endif - -std::ostream & getDebuggerStream(void) -{ - static ostream os(&debuggerBuffer()); - return os; -} - -// --------------------------------------------------------------------------- -// setNotifierHandler -// --------------------------------------------------------------------------- -// Specify a new handler for notifications. -// Does not throw. -// -extern "C" NotificationHandler -setNotifierHandler( NotificationHandler fn ) -{ - return notifierBuffer().setHandler( fn ); -} - -// --------------------------------------------------------------------------- -// setDebuggerHandler -// --------------------------------------------------------------------------- -// Specify a new handler for debugging notifications, only effective when -// Debug_Loris is defined, otherwise debugger does nothing. -// Does not throw. -// -extern "C" NotificationHandler -setDebuggerHandler( NotificationHandler fn ) -{ -#if defined( Debug_Loris ) - return debuggerBuffer().setHandler( fn ); -#else - fn = fn; - return NULL; -#endif -} - -} // end of namespace Loris - diff --git a/loris_library/Source/src/Notifier.h b/loris_library/Source/src/Notifier.h deleted file mode 100644 index c0269f2..0000000 --- a/loris_library/Source/src/Notifier.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef INCLUDE_NOTIFIER_H -#define INCLUDE_NOTIFIER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Notifier.h - * - * A pair of dedicated streams, notifier and debugger, are used for - * notification throughout the Loris class library. These streams are used - * like cout or cerr, but they buffer their contents until a newline is - * receieved. Then they post their entire contents to a notification - * handler. The default handler just prints to stderr, but other handlers - * may be dynamically specified using setNotifierHandler() and - * setDebuggerHandler(). - * - * debugger is enabled only when compiled with the preprocessor macro - * Debug_Loris defined. It cannot be enabled using setDebuggerHandler() if - * Debug_Loris is undefined.When Debug_Loris is not defined, characters - * streamed onto debugger are never posted nor are they otherwise - * accessible. - * - * Notifier.h may be included in c files. The stream declarations are - * omitted, but the notification handler routines are accessible. - * - * - * Kelly Fitz, 28 Feb 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - - -/* - * stream declaration, C++ only: - */ -#ifdef __cplusplus - -#include - -// begin namespace -namespace Loris { - -std::ostream & getNotifierStream(void); -std::ostream & getDebuggerStream(void); - -// declare streams: -static std::ostream & notifier = getNotifierStream(); -/* This stream is used throughout Loris (and may be used by clients) - to provide user feedback. Characters streamed onto notifier are - buffered until a newline is received, and then the entire contents - of the stream are flushed to the current notification handler (stderr, - by default). - */ - -static std::ostream & debugger = getDebuggerStream(); -/* This stream is used throughout Loris (and may be used by clients) - to provide debugging information. Characters streamed onto debugger are - buffered until a newline is received, and then the entire contents - of the stream are flushed to the current debugger handler (stderr, - by default). - - debugger is enabled only when compiled with the preprocessor macro - Debug_Loris defined. It cannot be enabled using setDebuggerHandler() - if Debug_Loris is undefined. When Debug_Loris is not defined, - characters streamed onto debugger are never posted nor are they - otherwise accessible. - */ - -// for convenience, import endl and ends from std into Loris: -using std::endl; -using std::ends; - -} // end of namespace Loris - -#endif /* def __cplusplus */ - -/* - * handler assignment, c linkable: - */ - -#ifdef __cplusplus -// begin namespace -namespace Loris { -extern "C" { -#endif // def __cplusplus - -// These functions do not throw exceptions. -typedef void(*NotificationHandler)(const char * s); -NotificationHandler setNotifierHandler( NotificationHandler fn ); -/* Specify a new handling procedure for posting user feedback, and return - the current handler. - */ - -NotificationHandler setDebuggerHandler( NotificationHandler fn ); -/* Specify a new handling procedure for posting debugging information, and return - the current handler. This has no effect unless compiled with the Debug_Loris - preprocessor macro defined. - */ - -#ifdef __cplusplus -} // end extern "C" -} // end of namespace Loris -#endif // def __cplusplus - - -#endif /* ndef INCLUDE_NOTIFIER_H */ diff --git a/loris_library/Source/src/Oscillator.cpp b/loris_library/Source/src/Oscillator.cpp deleted file mode 100644 index 1ffc5c5..0000000 --- a/loris_library/Source/src/Oscillator.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Oscillator.C - * - * Implementation of class Loris::Oscillator, a Bandwidth-Enhanced Oscillator. - * - * Kelly Fitz, 31 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Oscillator.h" - -#include "Filter.h" -#include "Partial.h" -#include "Notifier.h" - -#include -#include - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif -const double TwoPi = 2*Pi; - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// Oscillator construction -// --------------------------------------------------------------------------- -// Initialize stochastic modulators and state variables. -// -Oscillator::Oscillator( void ) : - m_modulator( 1.0 /* seed */ ), - m_filter( prototype_filter() ), - m_instfrequency( 0 ), - m_instamplitude( 0 ), - m_instbandwidth( 0 ), - m_determphase( 0 ) -{ -} - -// --------------------------------------------------------------------------- -// resetEnvelopes -// --------------------------------------------------------------------------- -// Reset the instantaneous envelope parameters -// (frequency, amplitude, bandwidth, and phase). -// The sample rate is needed to convert the -// Breakpoint frequency (Hz) to radians per sample. -// -void -Oscillator::resetEnvelopes( const Breakpoint & bp, double srate ) -{ - // Remember that the oscillator only knows about - // radian frequency! Convert! - m_instfrequency = bp.frequency() * TwoPi / srate; - m_instamplitude = bp.amplitude(); - m_instbandwidth = bp.bandwidth(); - m_determphase = bp.phase(); - - // clamp bandwidth: - if ( m_instbandwidth > 1. ) - { - debugger << "clamping bandwidth at 1." << endl; - m_instbandwidth = 1.; - } - else if ( m_instbandwidth < 0. ) - { - debugger << "clamping bandwidth at 0." << endl; - m_instbandwidth = 0.; - } - - // don't alias: - if ( m_instfrequency > Pi ) - { - debugger << "fading out aliasing Partial" << endl; - m_instamplitude = 0.; - } - - // Reset the fitler state too. - m_filter.clear(); - -} - -// --------------------------------------------------------------------------- -// m2pi -// --------------------------------------------------------------------------- -// O'Donnell's phase wrapping function. -// -static inline double m2pi( double x ) -{ - using namespace std; // floor should be in std - #define ROUND(x) (floor(.5 + (x))) - return x + ( TwoPi * ROUND(-x/TwoPi) ); -} - -// --------------------------------------------------------------------------- -// setPhase -// --------------------------------------------------------------------------- -// Reset the phase of the Oscillator to the specified -// value, and clear the accumulated phase modulation. (?) -// Or not. -// This is done when the amplitude of a Partial goes to -// zero, so that onsets are preserved in distilled -// and collated Partials. -// -void -Oscillator::setPhase( double ph ) -{ - m_determphase = m2pi(ph); -} - -// --------------------------------------------------------------------------- -// oscillate -// --------------------------------------------------------------------------- -// Accumulate bandwidth-enhanced sinusoidal samples modulating the -// oscillator state from its current values of radian frequency, -// amplitude, and bandwidth to the specified target values, into -// the specified half-open range of doubles. -// -// The caller must ensure that the range is valid. Target parameters -// are bounds-checked. -// -void -Oscillator::oscillate( double * begin, double * end, - const Breakpoint & bp, double srate ) -{ - double targetFreq = bp.frequency() * TwoPi / srate; // radians per sample - double targetAmp = bp.amplitude(); - double targetBw = bp.bandwidth(); - - // clamp bandwidth: - if ( targetBw > 1. ) - { - debugger << "clamping bandwidth at 1." << endl; - targetBw = 1.; - } - else if ( targetBw < 0. ) - { - debugger << "clamping bandwidth at 0." << endl; - targetBw = 0.; - } - - // don't alias: - if ( targetFreq > Pi ) // radian Nyquist rate - { - debugger << "fading out Partial above Nyquist rate" << endl; - targetAmp = 0.; - } - - // compute trajectories: - const double dTime = 1. / (end - begin); - const double dFreqOver2 = 0.5 * (targetFreq - m_instfrequency) * dTime; - // split frequency update in two steps, update phase using average - // frequency, after adding only half the frequency step - - const double dAmp = (targetAmp - m_instamplitude) * dTime; - const double dBw = (targetBw - m_instbandwidth) * dTime; - - // Use temporary local variables for speed. - // Probably not worth it when I am computing square roots - // and cosines... - double ph = m_determphase; - double f = m_instfrequency; - double a = m_instamplitude; - double bw = m_instbandwidth; - - // Also use a more efficient sample loop when the bandwidth is zero. - if ( 0 < bw || 0 < dBw ) - { - double am, nz; - for ( double * putItHere = begin; putItHere != end; ++putItHere ) - { - // use math functions in namespace std: - using namespace std; - - // compute amplitude modulation due to bandwidth: - // - // This will give the right amplitude modulation when scaled - // by the Partial amplitude: - // - // carrier amp: sqrt( 1. - bandwidth ) * amp - // modulation index: sqrt( 2. * bandwidth ) * amp - // - nz = m_filter.apply( m_modulator.sample() ); - am = sqrt( 1. - bw ) + ( nz * sqrt( 2. * bw ) ); - - // compute a sample and add it into the buffer: - *putItHere += am * a * cos( ph ); - - // update the instantaneous oscillator state: - f += dFreqOver2; - ph += f; // frequency is radians per sample - f += dFreqOver2; - a += dAmp; - bw += dBw; - if (bw < 0.) - { - bw = 0.; - } - } // end of sample computation loop - } - else - { - for ( double * putItHere = begin; putItHere != end; ++putItHere ) - { - // use math functions in namespace std: - using namespace std; - - // no modulation when there is no bandwidth - - // compute a sample and add it into the buffer: - *putItHere += a * cos( ph ); - - // update the instantaneous oscillator state: - f += dFreqOver2; - ph += f; // frequency is radians per sample - f += dFreqOver2; - a += dAmp; - } // end of sample computation loop - - } - - - // copy out of the local variables? - // no need because we are assigning to the target - // values below: - /* - m_instfrequency = f; - m_instamplitude = a; - m_instbandwidth = bw; - */ - - // wrap phase to prevent eventual loss of precision at - // high oscillation frequencies: - // (Doesn't really matter much exactly how we wrap it, - // as long as it brings the phase nearer to zero.) - m_determphase = m2pi( ph ); - - // set the state variables to their target values, - // just in case they didn't arrive exactly (overshooting - // amplitude or, especially, bandwidth, could be bad, and - // it does happen): - m_instfrequency = targetFreq; - m_instamplitude = targetAmp; - m_instbandwidth = targetBw; -} - -// --------------------------------------------------------------------------- -// protoype filter (static member) -// --------------------------------------------------------------------------- -// Static local function for obtaining a prototype Filter -// to use in Oscillator construction. Eventually, allow -// external (client) specification of the Filter prototype. -// -const Filter & -Oscillator::prototype_filter( void ) -{ - // Chebychev order 3, cutoff 500, ripple -1. - // - // Coefficients obtained from http://www.cs.york.ac.uk/~fisher/mkfilter/ - // Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher - // - static const double Gain = 4.663939184e+04; - static const double ExtraScaling = 6.; - static const double MaCoefs[] = { 1., 3., 3., 1. }; - static const double ArCoefs[] = { 1., -2.9258684252, 2.8580608586, -0.9320209046 }; - - static const Filter proto( MaCoefs, MaCoefs + 4, ArCoefs, ArCoefs + 4, ExtraScaling/Gain ); - return proto; -} - - - -} // end of namespace Loris diff --git a/loris_library/Source/src/Oscillator.h b/loris_library/Source/src/Oscillator.h deleted file mode 100644 index 79631f4..0000000 --- a/loris_library/Source/src/Oscillator.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef INCLUDE_OSCILLATOR_H -#define INCLUDE_OSCILLATOR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Oscillator.h - * - * Definition of class Loris::Oscillator, a Bandwidth-Enhanced Oscillator. - * - * Kelly Fitz, 31 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "NoiseGenerator.h" -#include "Filter.h" - -// begin namespace -namespace Loris { - -class Breakpoint; - -// --------------------------------------------------------------------------- -// class Oscillator -// -//! Class Oscillator represents the state of a single bandwidth-enhanced -//! sinusoidal oscillator used for synthesizing sounds from Reassigned -//! Bandwidth-Enhanced analysis data. Oscillator encapsulates the oscillator -//! state, including the instantaneous radian frequency (radians per -//! sample), amplitude, bandwidth coefficient, and phase, and a -//! bandlimited stochastic modulator. -//! -//! Class Synthesizer uses an instance of Oscillator to synthesize -//! bandwidth-enhanced Partials. -// -class Oscillator -{ -// --- implementation --- - - NoiseGenerator m_modulator; //! stochastic modulator - Filter m_filter; //! filter applied to the noise generator - - // instantaneous oscillator state: - double m_instfrequency; //! radians per sample - double m_instamplitude; //! absolute amplitude - double m_instbandwidth; //! bandwidth coefficient (noise energy / total energy) - - // accumulating phase state: - double m_determphase; //! deterministic phase in radians - -// --- interface --- -public: -// --- construction --- - - //! Construct a new Oscillator with all state parameters initialized to 0. - Oscillator( void ); - - // Copy, assignment, and destruction are free. - // - // Copied and assigned Oscillators have the duplicate state - // variables and the filters have the same coefficients, - // but the state of the filter delay lines is not copied. - -// --- oscillation --- - - //! Reset the instantaneous envelope parameters - //! (frequency, amplitude, bandwidth, and phase). - //! The sample rate is needed to convert the - //! Breakpoint frequency (Hz) to radians per sample. - void resetEnvelopes( const Breakpoint & bp, double srate ); - - //! Reset the phase of the Oscillator to the specified - //! value. This is done when the amplitude of a Partial - //! goes to zero, so that onsets are preserved in distilled - //! and collated Partials. - void setPhase( double ph ); - - //! Accumulate bandwidth-enhanced sinusoidal samples modulating the - //! oscillator state from its current values of radian frequency, amplitude, - //! and bandwidth to the specified target values. Accumulate samples into - //! the half-open (STL-style) range of doubles, starting at begin, and - //! ending before end (no sample is accumulated at end). The caller must - //! insure that the indices are valid. Target frequency and bandwidth are - //! checked to prevent aliasing and bogus bandwidth enhancement. - void oscillate( double * begin, double * end, - const Breakpoint & bp, double srate ); - -// --- accessors --- - - //! Return the instantaneous amplitde of the Oscillator. - double amplitude( void ) const { return m_instamplitude; } - - //! Return the instantaneous bandwidth of the Oscillator. - double bandwidth( void ) const { return m_instbandwidth; } - - //! Return the instantaneous phase of the Oscillator. - double phase( void ) const { return m_determphase; } - - //! Return the instantaneous radian frequency of the Oscillator. - double radianFreq( void ) const { return m_instfrequency; } - - //! Return access to the Filter used by this oscillator to - //! implement bandwidth-enhanced sinusoidal synthesis. - Filter & filter( void ) { return m_filter; } - -// --- static members --- - - //! Static local function for obtaining a prototype Filter - //! to use in Oscillator construction. Eventually, allow - //! external (client) specification of the Filter prototype. - static const Filter & prototype_filter( void ); - -}; // end of class Oscillator - -} // end of namespace Loris - -#endif /* ndef INCLUDE_OSCILLATOR_H */ diff --git a/loris_library/Source/src/Partial.cpp b/loris_library/Source/src/Partial.cpp deleted file mode 100644 index b6ea15c..0000000 --- a/loris_library/Source/src/Partial.cpp +++ /dev/null @@ -1,860 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Partial.C - * - * Implementation of class Loris::Partial. - * - * Kelly Fitz, 16 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Partial.h" -#include "Breakpoint.h" -#include "LorisExceptions.h" -#include "Notifier.h" - -#include -#include - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -// begin namespace -namespace Loris { - -//long Partial::DebugCounter = 0L; - -// comparitor for elements in Partial::container_type -typedef Partial::container_type::value_type Partial_value_type; -static -bool order_by_time( const Partial_value_type & x, const Partial_value_type & y ) -{ - // Partial_value_type is a (time,Breakpoint) pair - return x.first < y.first; -} - -// --- concering the type of Partial::container_type -// -// On the surface, it would seem that a vector of (time,Breakpoint) -// pairs would be a more efficient container for the Partial -// parameter envelope points, and the changes required to implement -// Partial using vector instead of map are minimal and simple. -// -// However, the crucial factor in that change is the expiration of -// Partial::iterators. With map, iterators remain valid after -// insertions and removals, but with vector they do not. So it -// is easy to change the container type, but it is a much harder -// project to find all the places in Loris that rely on iterators -// that remain valid after insertions and removals. -#undef USE_VECTOR - - -// -- construction -- - -// --------------------------------------------------------------------------- -// Partial constructor -// --------------------------------------------------------------------------- -//! Retun a new empty (no Breakpoints) unlabeled Partial. -// -Partial::Partial( void ) : - _label( 0 ) -{ -// ++DebugCounter; -} - -// --------------------------------------------------------------------------- -// Partial initialized constructor -// --------------------------------------------------------------------------- -//! Retun a new Partial from a half-open (const) iterator range -//! of time, Breakpoint pairs. -// -Partial::Partial( const_iterator beg, const_iterator end ) : - _breakpoints( beg._iter, end._iter ), - _label( 0 ) -{ -// ++DebugCounter; -} - -// --------------------------------------------------------------------------- -// Partial copy constructor -// --------------------------------------------------------------------------- -//! Return a new Partial that is an exact copy (has an identical set -//! of Breakpoints, at identical times, and the same label) of another -//! Partial. -// -Partial::Partial( const Partial & other ) : - _breakpoints( other._breakpoints ), - _label( other._label ) -{ -// ++DebugCounter; -} - -// --------------------------------------------------------------------------- -// Partial destructor -// --------------------------------------------------------------------------- -//! Destroy this Partial. -// -Partial::~Partial( void ) -{ -// --DebugCounter; -} - -// --------------------------------------------------------------------------- -// operator= -// --------------------------------------------------------------------------- -//! Make this Partial an exact copy (has an identical set of -//! Breakpoints, at identical times, and the same label) of another -//! Partial. -// -Partial & -Partial::operator=( const Partial & rhs ) -{ - if ( this != &rhs ) - { - _breakpoints = rhs._breakpoints; - _label = rhs._label; - } - return *this; -} - -// -- container-dependent implementation -- - -// --------------------------------------------------------------------------- -// begin -// --------------------------------------------------------------------------- -//! Return a const iterator refering to the position of the first -//! Breakpoint in this Partial's envelope. -// -Partial::const_iterator Partial::begin( void ) const -{ - return _breakpoints.begin(); -} - -//! Return an iterator refering to the position of the first -//! Breakpoint in this Partial's envelope. -// -Partial::iterator Partial::begin( void ) -{ - return _breakpoints.begin(); -} - -// --------------------------------------------------------------------------- -// end -// --------------------------------------------------------------------------- -//! Return a const iterator refering to the position past the last -//! Breakpoint in this Partial's envelope. The iterator returned by -//! end() (like the iterator returned by the end() member of any STL -//! container) does not refer to a valid Breakpoint. -// -Partial::const_iterator -Partial::end( void ) const -{ - return _breakpoints.end(); -} - -//! Return an iterator refering to the position past the last -//! Breakpoint in this Partial's envelope. The iterator returned by -//! end() (like the iterator returned by the end() member of any STL -//! container) does not refer to a valid Breakpoint. -// -Partial::iterator -Partial::end( void ) -{ - return _breakpoints.end(); -} - -// --------------------------------------------------------------------------- -// erase -// --------------------------------------------------------------------------- -//! Breakpoint removal: erase the Breakpoints in the specified range, -//! and return an iterator referring to the position after the, -//! erased range. -// -Partial::iterator -Partial::erase( Partial::iterator beg, Partial::iterator end ) -{ - _breakpoints.erase( beg._iter, end._iter ); - return end; -} - -// --------------------------------------------------------------------------- -// findAfter -// --------------------------------------------------------------------------- -//! Return a const iterator refering to the insertion position for a -//! Breakpoint at the specified time (that is, the position of the first -//! Breakpoint at a time not earlier than the specified time). -// -Partial::const_iterator -Partial::findAfter( double time ) const -{ -#if defined(USE_VECTOR) - // see note above - Partial_value_type dummy( time, Breakpoint() ); - return std::upper_bound( _breakpoints.begin(), _breakpoints.end(), dummy, order_by_time ); -#else - return _breakpoints.lower_bound( time ); -#endif -} - -//! Return an iterator refering to the insertion position for a -//! Breakpoint at the specified time (that is, the position of the first -//! Breakpoint at a time later than the specified time). -// -Partial::iterator -Partial::findAfter( double time ) -{ -#if defined(USE_VECTOR) - // see note above - Partial_value_type dummy( time, Breakpoint() ); - return std::upper_bound( _breakpoints.begin(), _breakpoints.end(), dummy, order_by_time ); -#else - return _breakpoints.lower_bound( time ); -#endif -} - -// --------------------------------------------------------------------------- -// insert -// --------------------------------------------------------------------------- -//! Breakpoint insertion: insert a copy of the specified Breakpoint in the -//! parameter envelope at time (seconds), and return an iterator -//! refering to the position of the inserted Breakpoint. -// -Partial::iterator -Partial::insert( double time, const Breakpoint & bp ) -{ -#if defined(USE_VECTOR) - // see note above - // find the position at which to insert the new Breakpoint: - Partial_value_type dummy( time, Breakpoint() ); - Partial::container_type::iterator insertHere = - std::lower_bound( _breakpoints.begin(), _breakpoints.end(), dummy, order_by_time ); - - // if the time at insertHere is equal to the insertion time, - // simply replace the Breakpoint, otherwise insert: - if ( insertHere->first == time ) - { - insertHere->second = bp; - } - else - { - insertHere = _breakpoints.insert( insertHere, Partial_value_type(time, bp) ); - } - return insertHere; -#else - /* - // this allows Breakpoints to be inserted arbitrarily - // close together, which is no good, can cause trouble later: - - std::pair< container_type::iterator, bool > result = - _breakpoints.insert( container_type::value_type(time, bp) ); - if ( ! result.second ) - { - result.first->second = bp; - } - return result.first; - */ - - // do not insert a Breakpoint closer than 1ns away - // from the nearest existing Breakpoint: - static const double MinTimeDif = 1.0E-9; // 1 ns - - // find the insertion point for this time - container_type::iterator pos = _breakpoints.lower_bound( time ); - - // the time of pos is either equal to or greater - // than the insertion time, if this is too close, - // remove the Breakpoint at pos: - if ( _breakpoints.end() != pos && MinTimeDif > pos->first - time ) - { - _breakpoints.erase( pos++ ); - } - // otherwise, if the preceding position is too clase, - // remove the Breakpoint at that position - else if ( _breakpoints.begin() != pos && MinTimeDif > time - (--pos)->first ) - { - _breakpoints.erase( pos++ ); - } - - // now pos is at most one position away from the insertion point - // so insertion can be performed in constant time, and the new - // Breakpoint is at least 1ns away from any other Breakpoint: - pos = _breakpoints.insert( pos, container_type::value_type(time, bp) ); - - Assert( pos->first == time ); - - return pos; - -#endif -} - -// --------------------------------------------------------------------------- -// numBreakpoints -// --------------------------------------------------------------------------- -//! Same as size(). Return the number of Breakpoints in this Partial. -// -Partial::size_type -Partial::numBreakpoints( void ) const -{ - return _breakpoints.size(); -} -// --------------------------------------------------------------------------- -// size -// --------------------------------------------------------------------------- -//! Return the number of Breakpoints in this Partial. -// -Partial::size_type -Partial::size( void ) const -{ - return _breakpoints.size(); -} - -// --------------------------------------------------------------------------- -// label -// --------------------------------------------------------------------------- -//! Return the 32-bit label for this Partial as an integer. -// -Partial::label_type -Partial::label( void ) const -{ - return _label; -} - -// --------------------------------------------------------------------------- -// first -// --------------------------------------------------------------------------- -//! Return a reference to the first Breakpoint in the Partial's -//! envelope. Raises InvalidPartial exception if there are no -//! Breakpoints. -// -Breakpoint & -Partial::first( void ) -{ - if ( size() == 0 ) - { - Throw( InvalidPartial, "Tried find first Breakpoint in a Partial with no Breakpoints." ); - } -#if defined(USE_VECTOR) - // see note above - return _breakpoints.front().second; -#else - return begin().breakpoint(); -#endif -} - -// --------------------------------------------------------------------------- -// first -// --------------------------------------------------------------------------- -//! Return a const reference to the first Breakpoint in the Partial's -//! envelope. Raises InvalidPartial exception if there are no -//! Breakpoints. -// -const Breakpoint & -Partial::first( void ) const -{ - if ( size() == 0 ) - { - Throw( InvalidPartial, "Tried find first Breakpoint in a Partial with no Breakpoints." ); - } -#if defined(USE_VECTOR) - // see note above - return _breakpoints.front().second; -#else - return begin().breakpoint(); -#endif -} - -// --------------------------------------------------------------------------- -// last -// --------------------------------------------------------------------------- -//! Return a reference to the last Breakpoint in the Partial's -//! envelope. Raises InvalidPartial exception if there are no -//! Breakpoints. -// -Breakpoint & -Partial::last( void ) -{ - if ( size() == 0 ) - { - Throw( InvalidPartial, "Tried find last Breakpoint in a Partial with no Breakpoints." ); - } -#if defined(USE_VECTOR) - // see note above - return _breakpoints.back().second; -#else - return (--end()).breakpoint(); -#endif -} - -// --------------------------------------------------------------------------- -// last -// --------------------------------------------------------------------------- -//! Return a const reference to the last Breakpoint in the Partial's -//! envelope. Raises InvalidPartial exception if there are no -//! Breakpoints. -// -const Breakpoint & -Partial::last( void ) const -{ - if ( size() == 0 ) - { - Throw( InvalidPartial, "Tried find last Breakpoint in a Partial with no Breakpoints." ); - } -#if defined(USE_VECTOR) - // see note above - return _breakpoints.back().second; -#else - return (--end()).breakpoint(); -#endif -} - -// -- container-independent implementation -- - -// --------------------------------------------------------------------------- -// initialPhase -// --------------------------------------------------------------------------- -//! Return starting phase in radians, except (InvalidPartial) if there -//! are no Breakpoints. -// -double -Partial::initialPhase( void ) const -{ - if ( numBreakpoints() == 0 ) - { - Throw( InvalidPartial, "Tried find intial phase of a Partial with no Breakpoints." ); - } - return first().phase(); -} - -// --------------------------------------------------------------------------- -// startTime -// --------------------------------------------------------------------------- -//! Return start time in seconds, except (InvalidPartial) if there -//! are no Breakpoints. -// -double -Partial::startTime( void ) const -{ - if ( numBreakpoints() == 0 ) - { - Throw( InvalidPartial, "Tried to find start time of a Partial with no Breakpoints." ); - } - return begin().time(); -} - -// --------------------------------------------------------------------------- -// endTime -// --------------------------------------------------------------------------- -//! Return end time in seconds, except (InvalidPartial) if there -//! are no Breakpoints. -// -double -Partial::endTime( void ) const -{ - if ( numBreakpoints() == 0 ) - { - Throw( InvalidPartial, "Tried to find end time of a Partial with no Breakpoints." ); - } - return (--end()).time(); -} - -// --------------------------------------------------------------------------- -// absorb -// --------------------------------------------------------------------------- -//! Absorb another Partial's energy as noise (bandwidth), -//! by accumulating the other's energy as noise energy -//! in the portion of this Partial's envelope that overlaps -//! (in time) with the other Partial's envelope. -// -void -Partial::absorb( const Partial & other ) -{ - Partial::iterator it = findAfter( other.startTime() ); - while ( it != end() && !(it.time() > other.endTime()) ) - { - // only non-null (non-zero-amplitude) Breakpoints - // abosrb noise energy because null Breakpoints - // are used especially to reset the Partial phase, - // and are not part of the normal analyasis data: - if ( it->amplitude() > 0 ) - { - // absorb energy from other at the time - // of this Breakpoint: - double a = other.amplitudeAt( it.time() ); - it->addNoiseEnergy( a * a ); - } - ++it; - } -} - -// --------------------------------------------------------------------------- -// setLabel -// --------------------------------------------------------------------------- -//! Set the label for this Partial to the specified 32-bit value. -// -void -Partial::setLabel( label_type l ) -{ - _label = l; -} - -// --------------------------------------------------------------------------- -// duration -// --------------------------------------------------------------------------- -//! Return time, in seconds, spanned by this Partial, or 0. if there -//! are no Breakpoints. -// -double -Partial::duration( void ) const -{ - if ( numBreakpoints() == 0 ) - { - return 0.; - } - return endTime() - startTime(); -} - -// --------------------------------------------------------------------------- -// erase -// --------------------------------------------------------------------------- -//! Erase the Breakpoint at the position of the -//! given iterator (invalidating the iterator), and -//! return an iterator referring to the next position, -//! or end if pos is the last Breakpoint in the Partial. -// -Partial::iterator -Partial::erase( iterator pos ) -{ - if ( pos != end() ) - { - iterator b= pos; - iterator e = ++pos; - pos = erase( b, e ); - } - return pos; -} - -// --------------------------------------------------------------------------- -// split -// --------------------------------------------------------------------------- -//! Break this Partial at the specified position (iterator). -//! The Breakpoint at the specified position becomes the first -//! Breakpoint in a new Partial. Breakpoints at the specified -//! position and subsequent positions are removed from this -//! Partial and added to the new Partial, which is returned. -// -Partial -Partial::split( iterator pos ) -{ - Partial res( pos, end() ); - erase( pos, end() ); - return res; -} - -// --------------------------------------------------------------------------- -// findNearest (const version) -// --------------------------------------------------------------------------- -//! Return the insertion position for the Breakpoint nearest -//! the specified time. Always returns a valid iterator (the -//! position of the nearest-in-time Breakpoint) unless there -//! are no Breakpoints. -// -Partial::const_iterator -Partial::findNearest( double time ) const -{ - // if there are no Breakpoints, return end: - if ( numBreakpoints() == 0 ) - { - return end(); - } - - // get the position of the first Breakpoint after time: - Partial::const_iterator pos = findAfter( time ); - - // if there is an earlier Breakpoint that is closer in - // time, prefer that one: - if ( pos != begin() ) - { - Partial::const_iterator prev = pos; - --prev; - if ( pos == end() || pos.time() - time > time - prev.time() ) - { - return prev; - } - } - - // failing all else: - return pos; -} - -// --------------------------------------------------------------------------- -// findNearest (non-const version) -// --------------------------------------------------------------------------- -//! Return the insertion position for the Breakpoint nearest -//! the specified time. Always returns a valid iterator (the -//! position of the nearest-in-time Breakpoint) unless there -//! are no Breakpoints. -// -Partial::iterator -Partial::findNearest( double time ) -{ - // if there are no Breakpoints, return end: - if ( numBreakpoints() == 0 ) - { - return end(); - } - // get the position of the first Breakpoint after time: - Partial::iterator pos = findAfter( time ); - - // if there is an earlier Breakpoint that is closer in - // time, prefer that one: - if ( pos != begin() ) - { - Partial::iterator prev = pos; - --prev; - if ( pos == end() || pos.time() - time > time - prev.time() ) - { - return prev; - } - } - - // failing all else: - return pos; -} - -// --------------------------------------------------------------------------- -// frequencyAt -// --------------------------------------------------------------------------- -//! Return the interpolated frequency (in Hz) of this Partial at the -//! specified time. At times beyond the ends of the Partial, return -//! the frequency at the nearest envelope endpoint. Throw an -//! InvalidPartial exception if this Partial has no Breakpoints. -// -double -Partial::frequencyAt( double time ) const -{ - Breakpoint bp = parametersAt( time ); - return bp.frequency(); -} - -// --------------------------------------------------------------------------- -// ShortestSafeFadeTime -// --------------------------------------------------------------------------- -//! Define the default fade time for computing amplitude at the ends -//! of a Partial. Floating point round-off errors make fadeTime == 0.0 -//! dangerous and unpredictable. 1 ns is short enough to prevent rounding -//! errors in the least significant bit of a 48-bit mantissa for times -//! up to ten hours. -// -const double Partial::ShortestSafeFadeTime = 1.0E-9; - -// --------------------------------------------------------------------------- -// amplitudeAt -// --------------------------------------------------------------------------- -//! Return the interpolated amplitude of this Partial at the -//! specified time. Throw an InvalidPartial exception if this -//! Partial has no Breakpoints. If non-zero fadeTime is specified, -//! then the amplitude at the ends of the Partial is coomputed using -//! a linear fade. The default fadeTime is ShortestSafeFadeTime, -//! see the definition of ShortestSafeFadeTime, above. -// -double -Partial::amplitudeAt( double time, double fadeTime ) const -{ - Breakpoint bp = parametersAt( time, fadeTime ); - return bp.amplitude(); -} - - -// --------------------------------------------------------------------------- -// phaseAt -// --------------------------------------------------------------------------- -//! Return the interpolated phase (in radians) of this Partial at -//! the specified time. At times beyond the ends of the Partial, -//! return the extrapolated from the nearest envelope endpoint -//! (assuming constant frequency, as reported by frequencyAt()). -//! -//! \param time is the time in seconds at which to evaluate the phase -//! -//! \throw Throw an InvalidPartial exception if this Partial has no -//! Breakpoints. -// -double -Partial::phaseAt( double time ) const -{ - Breakpoint bp = parametersAt( time ); - return bp.phase(); -} - -// --------------------------------------------------------------------------- -// bandwidthAt -// --------------------------------------------------------------------------- -//! Return the interpolated bandwidth (noisiness) coefficient of -//! this Partial at the specified time. At times beyond the ends of -//! the Partial, return the bandwidth coefficient at the nearest -//! envelope endpoint. Throw an InvalidPartial exception if this -//! Partial has no Breakpoints. -// -double -Partial::bandwidthAt( double time ) const -{ - Breakpoint bp = parametersAt( time ); - return bp.bandwidth(); -} - -// --------------------------------------------------------------------------- -// wrapPi -// --------------------------------------------------------------------------- -// O'Donnell's phase wrapping function. -// -static inline double wrapPi( double x ) -{ - using namespace std; // floor should be in std - #define ROUND(x) (floor(.5 + (x))) - const double TwoPi = 2.0*Pi; - return x + ( TwoPi * ROUND(-x/TwoPi) ); -} - -// --------------------------------------------------------------------------- -// parametersAt -// --------------------------------------------------------------------------- -//! Return the interpolated parameters of this Partial at -//! the specified time. If non-zero fadeTime is specified, then the -//! amplitude at the ends of the Partial is coomputed using a -//! linear fade. The default fadeTime is ShortestSafeFadeTime. -//! Throw an InvalidPartial exception if this Partial has no -//! Breakpoints. -// -Breakpoint -Partial::parametersAt( double time, double fadeTime ) const -{ - if ( numBreakpoints() == 0 ) - { - Throw( InvalidPartial, "Tried to interpolate a Partial with no Breakpoints." ); - } - - double freq, amp, bw, ph; - if ( startTime() >= time ) - { - // time is before the onset of the Partial: - // frequency is starting frequency, - // amplitude is 0 (or fading), bandwidth is starting - // bandwidth, and phase is rolled back. - - const Breakpoint & bp = first(); - double tstart = startTime(); - - // frequency: - freq = bp.frequency(); - - // amplitude: - amp = 0; - if ( (fadeTime > 0) && ((tstart - time) < fadeTime) ) - { - // fade in ampltude if time is before the onset of the Partial: - double alpha = 1. - ((tstart - time) / fadeTime); - amp = alpha * bp.amplitude(); - } - - // bandwidth: - bw = bp.bandwidth(); - - // phase: - double dp = 2. * Pi * (startTime() - time) * bp.frequency(); - ph = wrapPi( bp.phase() - dp ); - - } - else if ( endTime() <= time ) - { - // time is past the end of the Partial: - // frequency is ending frequency, - // amplitude is 0 (or fading), bandwidth is ending - // bandwidth, and phase is rolled forward. - const Breakpoint & bp = last(); - double tend = endTime(); - - // frequency: - freq = bp.frequency(); - - // amplitude: - amp = 0; - if ( (fadeTime > 0) && ((time - tend) < fadeTime) ) - { - // fade out ampltude if time is past the end of the Partial: - double alpha = 1. - ((time - tend) / fadeTime); - amp = alpha * bp.amplitude(); - } - - // bandwidth: - bw = bp.bandwidth(); - - // phase: - double dp = 2. * Pi * (time - endTime()) * bp.frequency(); - ph = wrapPi( bp.phase() + dp ); - } - else - { - // findAfter returns the position of the earliest - // Breakpoint later than time, or the end - // position if no such Breakpoint exists: - Partial::const_iterator it = findAfter( time ); - - // interpolate between it and its predeccessor - // (we checked already that it is not begin or end): - const Breakpoint & hi = it.breakpoint(); - double hitime = it.time(); - const Breakpoint & lo = (--it).breakpoint(); - double lotime = it.time(); - - double alpha = (time - lotime) / (hitime - lotime); - - // frequency: - freq = (alpha * hi.frequency()) + ((1. - alpha) * lo.frequency()); - - // amplitude: - amp = (alpha * hi.amplitude()) + ((1. - alpha) * lo.amplitude()); - - // bandwidth: - bw = (alpha * hi.bandwidth()) + ((1. - alpha) * lo.bandwidth()); - - // phase: - // interpolated phase is computed from the interpolated frequency - // and offset from the phase of the preceding Breakpoint: - double favg = 0.5 * ( lo.frequency() + freq ); // + hi.frequency() ); - double dp = 2. * Pi * (time - lotime) * favg; - ph = wrapPi( lo.phase() + dp ); - } - - return Breakpoint( freq, amp, bw, ph ); -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Partial.h b/loris_library/Source/src/Partial.h deleted file mode 100644 index 1b26871..0000000 --- a/loris_library/Source/src/Partial.h +++ /dev/null @@ -1,786 +0,0 @@ -#ifndef INCLUDE_PARTIAL_H -#define INCLUDE_PARTIAL_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Partial.h - * - * Definition of class Loris::Partial, and definitions and implementations of - * classes of const and non-const iterators over Partials, and the exception - * class InvalidPartial, thrown by some Partial members when invoked on a - * degenerate Partial having no Breakpoints. - * - * Kelly Fitz, 16 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Breakpoint.h" -#include "LorisExceptions.h" - -#include -//#include -//#include - -// begin namespace -namespace Loris { - -class Partial_Iterator; -class Partial_ConstIterator; - -// --------------------------------------------------------------------------- -// class Partial -// -//! An instance of class Partial represents a single component in the -//! reassigned bandwidth-enhanced additive model. A Partial consists of a -//! chain of Breakpoints describing the time-varying frequency, amplitude, -//! and bandwidth (or noisiness) envelopes of the component, and a 4-byte -//! label. The Breakpoints are non-uniformly distributed in time. For more -//! information about Reassigned Bandwidth-Enhanced Analysis and the -//! Reassigned Bandwidth-Enhanced Additive Sound Model, refer to the Loris -//! website: www.cerlsoundgroup.org/Loris/. -//! -//! The constituent time-tagged Breakpoints are accessible through -//! Partial:iterator and Partial::const_iterator interfaces. -//! These iterator classes implement the interface for bidirectional -//! iterators in the STL, including pre and post-increment and decrement, -//! and dereferencing. Dereferencing a Partial::itertator or -//! Partial::const_itertator yields a reference to a Breakpoint. Additionally, -//! these iterator classes have breakpoint() and time() members, returning -//! the Breakpoint (by reference) at the current iterator position and the -//! time (by value) corresponding to that Breakpoint. -//! -//! Partial is a leaf class, do not subclass. -//! -//! Most of the implementation of Partial delegates to a few -//! container-dependent members. The following members are -//! container-dependent, the other members are implemented in -//! terms of these: -//! default construction -//! copy (construction) -//! operator= (assign) -//! operator== (equivalence) -//! size -//! insert( pos, Breakpoint ) -//! erase( b, e ) -//! findAfter( time ) -//! begin (const and non-const) -//! end (const and non-const) -//! first (const and non-const) -//! last (const and non-const) -// -class Partial -{ -// -- public interface -- -public: - -// -- types -- - - //! underlying Breakpoint container type, used by - //! the iterator types defined below: - typedef std::map< double, Breakpoint > container_type; - - // typedef std::vector< std::pair< double, Breakpoint > > container_type; - // see Partial.C for a discussion of issues surrounding the - // choice of std::map as a Breakpoint container. - - //! 32 bit type for labeling Partials - typedef int label_type; - - //! non-const iterator over (time, Breakpoint) pairs in this Partial - typedef Partial_Iterator iterator; - - //! const iterator over (time, Breakpoint) pairs in this Partial - typedef Partial_ConstIterator const_iterator; - - //! size type for number of Breakpoints in this Partial - typedef container_type::size_type size_type; - -// -- construction -- - - //! Retun a new empty (no Breakpoints) Partial. - Partial( void ); - - //! Retun a new Partial from a half-open (const) iterator range - //! of time-Breakpoint pairs. - //! - //! \param beg is the beginning of the range of time-Breakpoint - //! pairs to insert into the new Partial. - //! \param end is the end of the range of time-Breakpoint pairs - //! to insert into the new Partial. - Partial( const_iterator beg, const_iterator end ); - - //! Return a new Partial that is an exact copy (has an identical set - //! of Breakpoints, at identical times, and the same label) of another - //! Partial. - //! - //! \param other is the Partial to copy. - Partial( const Partial & other ); - - //! Destroy this Partial. - ~Partial( void ); - -// -- assignment -- - - //! Make this Partial an exact copy (has an identical set of - //! Breakpoints, at identical times, and the same label) of another - //! Partial. - //! - //! \param other is the Partial to copy. - Partial & operator=( const Partial & other ); - -// -- container-dependent implementation -- - - //! Return an iterator refering to the position of the first - //! Breakpoint in this Partial's envelope, or end() if there - //! are no Breakpoints in the Partial. - iterator begin( void ); - - //! Return a const iterator refering to the position of the first - //! Breakpoint in this Partial's envelope, or end() if there - //! are no Breakpoints in the Partial. - const_iterator begin( void ) const; - - //! Return an iterator refering to the position past the last - //! Breakpoint in this Partial's envelope. The iterator returned by - //! end() (like the iterator returned by the end() member of any STL - //! container) does not refer to a valid Breakpoint. - iterator end( void ); - - //! Return a const iterator refering to the position past the last - //! Breakpoint in this Partial's envelope. The iterator returned by - //! end() (like the iterator returned by the end() member of any STL - //! container) does not refer to a valid Breakpoint. - const_iterator end( void ) const; - - //! Breakpoint removal: erase the Breakpoints in the specified range, - //! and return an iterator referring to the position after the, - //! erased range. - //! - //! \param beg is the beginning of the range of Breakpoints to erase - //! \param end is the end of the range of Breakpoints to erase - //! \return The position of the first Breakpoint after the range - //! of removed Breakpoints, or end() if the last Breakpoint - //! in the Partial was removed. - iterator erase( iterator beg, iterator end ); - - //! Return an iterator refering to the insertion position for a - //! Breakpoint at the specified time (that is, the position of the first - //! Breakpoint at a time later than the specified time). - //! - //! \param time is the time in seconds to find - //! \return The last position (iterator) at which a Breakpoint at the - //! specified time could be inserted (the position of the - //! first Breakpoint later than time). - iterator findAfter( double time ); - - //! Return a const iterator refering to the insertion position for a - //! Breakpoint at the specified time (that is, the position of the first - //! Breakpoint at a time later than the specified time). - //! - //! \param time is the time in seconds to find - //! \return The last position (iterator) at which a Breakpoint at the - //! specified time could be inserted (the position of the - //! first Breakpoint later than time). - const_iterator findAfter( double time ) const; - - //! Breakpoint insertion: insert a copy of the specified Breakpoint in the - //! parameter envelope at time (seconds), and return an iterator - //! refering to the position of the inserted Breakpoint. - //! - //! \param time is the time in seconds at which to insert the new - //! Breakpoint. - //! \param bp is the new Breakpoint to insert. - //! \return the position (iterator) of the newly-inserted - //! time-Breakpoint pair. - iterator insert( double time, const Breakpoint & bp ); - - //! Return the number of Breakpoints in this Partial. - //! - //! \return The number of Breakpoints in this Partial. - size_type size( void ) const; - -// -- access -- - - //! Return the duration (in seconds) spanned by the Breakpoints in - //! this Partial. Note that the synthesized onset time will differ, - //! depending on the fade time used to synthesize this Partial (see - //! class Synthesizer). - double duration( void ) const; - - //! Return the time (in seconds) of the last Breakpoint in this - //! Partial. Note that the synthesized onset time will differ, - //! depending on the fade time used to synthesize this Partial (see - //! class Synthesizer). - double endTime( void ) const; - - //! Return a reference to the first Breakpoint in the Partial's - //! envelope. - //! - //! \throw InvalidPartial if there are no Breakpoints. - Breakpoint & first( void ); - - //! Return a const reference to the first Breakpoint in the Partial's - //! envelope. - //! - //! \throw InvalidPartial if there are no Breakpoints. - const Breakpoint & first( void ) const; - - //! Return the phase (in radians) of this Partial at its start time - //! (the phase of the first Breakpoint). Note that the initial - //! synthesized phase will differ, depending on the fade time used - //! to synthesize this Partial (see class Synthesizer). - double initialPhase( void ) const; - - //! Return the 32-bit label for this Partial as an integer. - label_type label( void ) const; - - //! Return a reference to the last Breakpoint in the Partial's - //! envelope. - //! - //! \throw InvalidPartial if there are no Breakpoints. - Breakpoint & last( void ); - - //! Return a const reference to the last Breakpoint in the Partial's - //! envelope. - //! - //! \throw InvalidPartial if there are no Breakpoints. - const Breakpoint & last( void ) const; - - //! Same as size(). Return the number of Breakpoints in this Partial. - size_type numBreakpoints( void ) const; - - //! Return the time (in seconds) of the first Breakpoint in this - //! Partial. Note that the synthesized onset time will differ, - //! depending on the fade time used to synthesize this Partial (see - //! class Synthesizer). - double startTime( void ) const; - -// -- mutation -- - - //! Absorb another Partial's energy as noise (bandwidth), - //! by accumulating the other's energy as noise energy - //! in the portion of this Partial's envelope that overlaps - //! (in time) with the other Partial's envelope. - //! - //! \param other is the Partial to absorb. - void absorb( const Partial & other ); - - //! Set the label for this Partial to the specified 32-bit value. - void setLabel( label_type l ); - - //! Remove the Breakpoint at the position of the given - //! iterator, invalidating the iterator. Return a - //! iterator referring to the next valid position, or to - //! the end of the Partial if the last Breakpoint is removed. - //! - //! \param pos is the position of the time-Breakpoint pair - //! to be removed. - //! \return The position (iterator) of the time-Breakpoint - //! pair after the one that was removed. - //! \post The iterator pos is invalid. - iterator erase( iterator pos ); - - //! Return an iterator refering to the position of the - //! Breakpoint in this Partial nearest the specified time. - //! - //! \param time is the time to find. - //! \return The position (iterator) of the time-Breakpoint - //! pair nearest (in time) to the specified time. - iterator findNearest( double time ); - - //! Return a const iterator refering to the position of the - //! Breakpoint in this Partial nearest the specified time. - //! - //! \param time is the time to find. - //! \return The position (iterator) of the time-Breakpoint - //! pair nearest (in time) to the specified time. - const_iterator findNearest( double time ) const; - - //! Break this Partial at the specified position (iterator). - //! The Breakpoint at the specified position becomes the first - //! Breakpoint in a new Partial. Breakpoints at the specified - //! position and subsequent positions are removed from this - //! Partial and added to the new Partial, which is returned. - //! - //! \param pos is the position at which to split this Partial. - //! \return A new Partial consisting of time-Breakpoint pairs - //! beginning with pos and extending to the end of this - //! Partial. - //! \post All positions beginning with pos and extending to - //! the end of this Partial have been removed. - Partial split( iterator pos ); - -// -- parameter interpolation/extrapolation -- - - //! Define the default fade time for computing amplitude at the ends - //! of a Partial. Floating point round-off errors make fadeTime == 0.0 - //! dangerous and unpredictable. 1 ns is short enough to prevent rounding - //! errors in the least significant bit of a 48-bit mantissa for times - //! up to ten hours. - //! - //! 1 nanosecond, see Partial.C - static const double ShortestSafeFadeTime; - - //! Return the interpolated amplitude of this Partial at the - //! specified time. If non-zero fadeTime is specified, - //! then the amplitude at the ends of the Partial is computed using - //! a linear fade. The default fadeTime is ShortestSafeFadeTime, - //! see the definition of ShortestSafeFadeTime, above. - //! - //! \param time is the time in seconds at which to evaluate the - //! Partial. - //! \param fadeTime is the duration in seconds over which Partial - //! amplitudes fade at the ends. The default value is - //! ShortestSafeFadeTime, 1 ns. - //! \return The amplitude of this Partial at the specified time. - //! \pre The Partial must have at least one Breakpoint. - //! \throw InvalidPartial if the Partial has no Breakpoints. - double amplitudeAt( double time, double fadeTime = ShortestSafeFadeTime ) const; - - //! Return the interpolated bandwidth (noisiness) coefficient of - //! this Partial at the specified time. At times beyond the ends of - //! the Partial, return the bandwidth coefficient at the nearest - //! envelope endpoint. - //! - //! \param time is the time in seconds at which to evaluate the - //! Partial. - //! \return The bandwidth of this Partial at the specified time. - //! \pre The Partial must have at least one Breakpoint. - //! \throw InvalidPartial if the Partial has no Breakpoints. - double bandwidthAt( double time ) const; - - //! Return the interpolated frequency (in Hz) of this Partial at the - //! specified time. At times beyond the ends of the Partial, return - //! the frequency at the nearest envelope endpoint. - //! - //! \param time is the time in seconds at which to evaluate the - //! Partial. - //! \return The frequency of this Partial at the specified time. - //! \pre The Partial must have at least one Breakpoint. - //! \throw InvalidPartial if the Partial has no Breakpoints. - double frequencyAt( double time ) const; - - //! Return the interpolated phase (in radians) of this Partial at - //! the specified time. At times beyond the ends of the Partial, - //! return the extrapolated from the nearest envelope endpoint - //! (assuming constant frequency, as reported by frequencyAt()). - //! - //! \param time is the time in seconds at which to evaluate the - //! Partial. - //! \return The phase of this Partial at the specified time. - //! \pre The Partial must have at least one Breakpoint. - //! \throw InvalidPartial if the Partial has no Breakpoints. - double phaseAt( double time ) const; - - //! Return the interpolated parameters of this Partial at - //! the specified time, same as building a Breakpoint from - //! the results of frequencyAt, ampitudeAt, bandwidthAt, and - //! phaseAt, but performs only one Breakpoint envelope search. - //! If non-zero fadeTime is specified, then the - //! amplitude at the ends of the Partial is coomputed using a - //! linear fade. The default fadeTime is ShortestSafeFadeTime. - //! - //! \param time is the time in seconds at which to evaluate the - //! Partial. - //! \param fadeTime is the duration in seconds over which Partial - //! amplitudes fade at the ends. The default value is - //! ShortestSafeFadeTime, 1 ns. - //! \return A Breakpoint describing the parameters of this Partial - //! at the specified time. - //! \pre The Partial must have at least one Breakpoint. - //! \throw InvalidPartial if the Partial has no Breakpoints. - Breakpoint parametersAt( double time, double fadeTime = ShortestSafeFadeTime ) const; - -// -- implementation -- -private: - - label_type _label; - container_type _breakpoints; // Breakpoint envelope - -}; // end of class Partial - -// --------------------------------------------------------------------------- -// class Partial_Iterator -// -//! Non-const iterator for the Loris::Partial Breakpoint map. Wraps -//! the non-const iterator for the (time,Breakpoint) pair container -//! Partial::container_type. Partial_Iterator implements a -//! bidirectional iterator interface, and additionally offers time -//! and Breakpoint (reference) access through time() and breakpoint() -//! members. -// -class Partial_Iterator -{ -// -- instance variables -- - - typedef Partial::container_type BaseContainer; - typedef BaseContainer::iterator BaseIterator; - BaseIterator _iter; - -// -- public interface -- -public: -// -- bidirectional iterator interface -- - - //! The iterator category, for copmpatibility with - //! C++ standard library algorithms - typedef BaseIterator::iterator_category iterator_category; - - //! The type of element that can be accessed through this - //! iterator (Breakpoint). - typedef Breakpoint value_type; - - //! The type representing the distance between two of these - //! iterators. - typedef BaseIterator::difference_type difference_type; - - //! The type of a pointer to the type of element that can - //! be accessed through this iterator (Breakpoint *). - typedef Breakpoint * pointer; - - //! The type of a reference to the type of element that can - //! be accessed through this iterator (Breakpoint &). - typedef Breakpoint & reference; - -// construction: - - //! Construct a new iterator referring to no position in - //! any Partial. - Partial_Iterator( void ) {} - - // (allow compiler to generate copy, assignment, and destruction) - -// pre-increment/decrement: - - //! Pre-increment operator - advance the position of the iterator - //! and return the iterator itself. - //! - //! \return This iterator (reference to self). - //! \pre The iterator must be a valid position before the end - //! in some Partial. - Partial_Iterator& operator ++ () { ++_iter; return *this; } - - //! Pre-decrement operator - move the position of the iterator - //! back by one and return the iterator itself. - //! - //! \return This iterator (reference to self). - //! \pre The iterator must be a valid position after the beginning - //! in some Partial. - Partial_Iterator& operator -- () { --_iter; return *this; } - -// post-increment/decrement: - - //! Post-increment operator - advance the position of the iterator - //! and return a copy of the iterator before it was advanced. - //! The int argument is unused compiler magic. - //! - //! \return An iterator that is a copy of this iterator before - //! being advanced. - //! \pre The iterator must be a valid position before the end - //! in some Partial. - Partial_Iterator operator ++ ( int ) { return Partial_Iterator( _iter++ ); } - - //! Post-decrement operator - move the position of the iterator - //! back by one and return a copy of the iterator before it was - //! decremented. The int argument is unused compiler magic. - //! - //! \return An iterator that is a copy of this iterator before - //! being decremented. - //! \pre The iterator must be a valid position after the beginning - //! in some Partial. - Partial_Iterator operator -- ( int ) { return Partial_Iterator( _iter-- ); } - -// dereference (for treating Partial like a -// STL collection of Breakpoints): - - //! Dereference operator. - //! - //! \return A reference to the Breakpoint at the position of this - //! iterator. - Breakpoint & operator * ( void ) const { return breakpoint(); } - - - //! Dereference operator. - //! - //! \return A reference to the Breakpoint at the position of this - //! iterator. - //Breakpoint & operator * ( void ) { return breakpoint(); } - - //! Pointer operator. - //! - //! \return A pointer to the Breakpoint at the position of this - //! iterator. - Breakpoint * operator -> ( void ) const { return & breakpoint(); } - - //! Pointer operator. - //! - //! \return A pointer to the Breakpoint at the position of this - //! iterator. - //Breakpoint * operator -> ( void ) { return & breakpoint(); } - -// comparison: - - //! Equality comparison operator. - //! - //! \param lhs the iterator on the left side of the operator. - //! \param rhs the iterator on the right side of the operator. - //! \return true if the two iterators refer to the same position - //! in the same Partial, false otherwise. - friend bool operator == ( const Partial_Iterator & lhs, - const Partial_Iterator & rhs ) - { return lhs._iter == rhs._iter; } - - //! Inequality comparison operator. - //! - //! \param lhs the iterator on the left side of the operator. - //! \param rhs the iterator on the right side of the operator. - //! \return false if the two iterators refer to the same position - //! in the same Partial, true otherwise. - friend bool operator != ( const Partial_Iterator & lhs, - const Partial_Iterator & rhs ) - { return lhs._iter != rhs._iter; } - -// -- time and Breakpoint access -- - - //! Breakpoint accessor. - //! - //! \return A const reference to the Breakpoint at the position of this - //! iterator. - Breakpoint & breakpoint( void ) const - { return _iter->second; } - - //! Breakpoint accessor. - //! - //! \return A reference to the Breakpoint at the position of this - //! iterator. - //Breakpoint & breakpoint( void ) - // { return _iter->second; } - - //! Time accessor. - //! - //! \return The time in seconds of the Breakpoint at the position - //! of this iterator. - double time( void ) const - { return _iter->first; } - -// -- BaseIterator conversions -- -private: - // construction by GenericBreakpointContainer from a BaseIterator: - Partial_Iterator( const BaseIterator & it ) : - _iter(it) {} - - friend class Partial; - - // befriend Partial_ConstIterator, - // for const construction from non-const: - friend class Partial_ConstIterator; - -}; // end of class Partial_Iterator - -// --------------------------------------------------------------------------- -// class Partial_ConstIterator -// -//! Const iterator for the Loris::Partial Breakpoint map. Wraps -//! the non-const iterator for the (time,Breakpoint) pair container -//! Partial::container_type. Partial_Iterator implements a -//! bidirectional iterator interface, and additionally offers time -//! and Breakpoint (reference) access through time() and breakpoint() -//! members. -// -class Partial_ConstIterator -{ -// -- instance variables -- - typedef Partial::container_type BaseContainer; - typedef BaseContainer::const_iterator BaseIterator; - BaseIterator _iter; - -// -- public interface -- -public: -// -- bidirectional iterator interface -- - - //! The iterator category, for copmpatibility with - //! C++ standard library algorithms - typedef BaseIterator::iterator_category iterator_category; - - //! The type of element that can be accessed through this - //! iterator (Breakpoint). - typedef Breakpoint value_type; - - //! The type representing the distance between two of these - //! iterators. - typedef BaseIterator::difference_type difference_type; - - //! The type of a pointer to the type of element that can - //! be accessed through this iterator (const Breakpoint *). - typedef const Breakpoint * pointer; - - //! The type of a reference to the type of element that can - //! be accessed through this iterator (const Breakpoint &). - typedef const Breakpoint & reference; - -// construction: - - //! Construct a new iterator referring to no position in - //! any Partial. - Partial_ConstIterator( void ) {} - - //! Construct a new const iterator from a non-const iterator. - //! - //! \param other a non-const iterator from which to make - //! a read-only copy. - Partial_ConstIterator( const Partial_Iterator & other ) : - _iter( other._iter ) {} - - // (allow compiler to generate copy, assignment, and destruction): - -// pre-increment/decrement: - - //! Pre-increment operator - advance the position of the iterator - //! and return the iterator itself. - //! - //! \return This iterator (reference to self). - //! \pre The iterator must be a valid position before the end - //! in some Partial. - Partial_ConstIterator& operator ++ () { ++_iter; return *this; } - - //! Pre-decrement operator - move the position of the iterator - //! back by one and return the iterator itself. - //! - //! \return This iterator (reference to self). - //! \pre The iterator must be a valid position after the beginning - //! in some Partial. - Partial_ConstIterator& operator -- () { --_iter; return *this; } - -// post-increment/decrement: - - //! Post-increment operator - advance the position of the iterator - //! and return a copy of the iterator before it was advanced. - //! The int argument is unused compiler magic. - //! - //! \return An iterator that is a copy of this iterator before - //! being advanced. - //! \pre The iterator must be a valid position before the end - //! in some Partial. - Partial_ConstIterator operator ++ ( int ) { return Partial_ConstIterator( _iter++ ); } - - //! Post-decrement operator - move the position of the iterator - //! back by one and return a copy of the iterator before it was - //! decremented. The int argument is unused compiler magic. - //! - //! \return An iterator that is a copy of this iterator before - //! being decremented. - //! \pre The iterator must be a valid position after the beginning - //! in some Partial. - Partial_ConstIterator operator -- ( int ) { return Partial_ConstIterator( _iter-- ); } - -// dereference (for treating Partial like a -// STL collection of Breakpoints): - - //! Dereference operator. - //! - //! \return A const reference to the Breakpoint at the position of this - //! iterator. - const Breakpoint & operator * ( void ) const { return breakpoint(); } - - //! Pointer operator. - //! - //! \return A const pointer to the Breakpoint at the position of this - //! iterator. - const Breakpoint * operator -> ( void ) const { return & breakpoint(); } - -// comparison: - - //! Equality comparison operator. - //! - //! \param lhs the iterator on the left side of the operator. - //! \param rhs the iterator on the right side of the operator. - //! \return true if the two iterators refer to the same position - //! in the same Partial, false otherwise. - friend bool operator == ( const Partial_ConstIterator & lhs, - const Partial_ConstIterator & rhs ) - { return lhs._iter == rhs._iter; } - - //! Inequality comparison operator. - //! - //! \param lhs the iterator on the left side of the operator. - //! \param rhs the iterator on the right side of the operator. - //! \return false if the two iterators refer to the same position - //! in the same Partial, true otherwise. - friend bool operator != ( const Partial_ConstIterator & lhs, - const Partial_ConstIterator & rhs ) - { return lhs._iter != rhs._iter; } - -// -- time and Breakpoint access -- - - //! Breakpoint accessor. - //! - //! \return A const reference to the Breakpoint at the position of this - //! iterator. - const Breakpoint & breakpoint( void ) const - { return _iter->second; } - - //! Time accessor. - //! - //! \return The time in seconds of the Breakpoint at the position - //! of this iterator. - double time( void ) const - { return _iter->first; } - -// -- BaseIterator conversions -- -private: - // construction by GenericBreakpointContainer from a BaseIterator: - Partial_ConstIterator( BaseIterator it ) : - _iter(it) {} - - friend class Partial; - -}; // end of class Partial_ConstIterator - -// --------------------------------------------------------------------------- -// class InvalidPartial -// -//! Class of exceptions thrown when a Partial is found to be badly configured -//! or otherwise invalid. -// -class InvalidPartial : public InvalidObject -{ -public: - - //! Construct a new instance with the specified description and, optionally - //! a string identifying the location at which the exception as thrown. The - //! Throw( Exception_Class, description_string ) macro generates a location - //! string automatically using __FILE__ and __LINE__. - //! - //! \param str is a string describing the exceptional condition - //! \param where is an option string describing the location in - //! the source code from which the exception was thrown - //! (generated automatically byt he Throw macro). - InvalidPartial( const std::string & str, const std::string & where = "" ) : - InvalidObject( std::string("Invalid Partial -- ").append( str ), where ) {} - -}; // end of class InvalidPartial - -} // end of namespace Loris - -#endif /* ndef INCLUDE_PARTIAL_H */ diff --git a/loris_library/Source/src/PartialBuilder.cpp b/loris_library/Source/src/PartialBuilder.cpp deleted file mode 100644 index f1ce3be..0000000 --- a/loris_library/Source/src/PartialBuilder.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PartialBuilder.C - * - * Implementation of a class representing a policy for connecting peaks - * extracted from a reassigned time-frequency spectrum to form ridges - * and construct Partials. - * - * This strategy attemps to follow a mFreqWarping frequency envelope when - * forming Partials, by prewarping all peak frequencies according to the - * (inverse of) frequency mFreqWarping envelope. At the end of the analysis, - * Partial frequencies need to be un-warped by calling fixPartialFrequencies(). - * - * The first attempt was the same as the basic partial formation strategy, - * but for purposes of matching, peak frequencies are scaled by the ratio - * of the mFreqWarping envelope's value at the previous frame to its value - * at the current frame. This was not adequate, didn't store enough history - * so it wasn't really following the reference envelope, just using it to - * make a local decision about how frequency should drift from one frame to - * the next. - * - * Kelly Fitz, 28 May 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "PartialBuilder.h" - -#include "BreakpointEnvelope.h" -#include "Envelope.h" -#include "Notifier.h" -#include "Partial.h" -#include "PartialList.h" -#include "PartialPtrs.h" -#include "SpectralPeaks.h" - -#include -#include - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- -// HEY - remove mMaxTimeOffset and the hopTime argument, these are wrong -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// construction -// --------------------------------------------------------------------------- -// Construct a new builder that constrains Partial frequnecy -// drift by the specified drift value in Hz. -// -PartialBuilder::PartialBuilder( double drift ) : - mFreqWarping( new BreakpointEnvelope(1.0) ), - mFreqDrift( drift ) -{ -} - -// --------------------------------------------------------------------------- -// construction -// --------------------------------------------------------------------------- -// Construct a new builder that constrains Partial frequnecy -// drift by the specified drift value in Hz. The frequency -// warping envelope is applied to the spectral peak frequencies -// and the frequency drift parameter in each frame before peaks -// are linked to eligible Partials. All the Partial frequencies -// need to be un-warped at the ned of the building process, by -// calling finishBuilding(). -// -PartialBuilder::PartialBuilder( double drift, const Envelope & env ) : - mFreqWarping( env.clone() ), - mFreqDrift( drift ) -{ -} - -// --- local helpers for Partial building --- - -// --------------------------------------------------------------------------- -// end_frequency -// --------------------------------------------------------------------------- -// Return the frequency of the last Breakpoint in a Partial. -// -static inline double end_frequency( const Partial & partial ) -{ - return partial.last().frequency(); -} - -// --------------------------------------------------------------------------- -// freq_distance -// --------------------------------------------------------------------------- -// Helper function, used in formPartials(). -// Returns the (positive) frequency distance between a Breakpoint -// and the last Breakpoint in a Partial. -// -inline double -PartialBuilder::freq_distance( const Partial & partial, const SpectralPeak & pk ) -{ - double normBpFreq = pk.frequency() / mFreqWarping->valueAt( pk.time() ); - - double normPartialEndFreq = - partial.last().frequency() / mFreqWarping->valueAt( partial.endTime() ); - - return std::fabs( normPartialEndFreq - normBpFreq ); -} - -// --------------------------------------------------------------------------- -// better_match -// --------------------------------------------------------------------------- -// Predicate for choosing the better of two proposed -// Partial-to-Breakpoint matches. Note: sometimes this -// is used to compare two candidate Breakpoint matches -// to the same Partial, other times to candidate Partials -// to the same Breakpoint. -// -// Return true if the first match is better, otherwise -// return false. -// - -bool PartialBuilder::better_match( const Partial & part, const SpectralPeak & pk1, - const SpectralPeak & pk2 ) -{ - Assert( part.numBreakpoints() > 0 ); - - return freq_distance( part, pk1 ) < freq_distance( part, pk2 ); -} - -bool PartialBuilder::better_match( const Partial & part1, - const Partial & part2, const SpectralPeak & pk ) -{ - Assert( part1.numBreakpoints() > 0 ); - Assert( part2.numBreakpoints() > 0 ); - - return freq_distance( part1, pk ) < freq_distance( part2, pk ); -} - -// --- Partial building members --- - -// --------------------------------------------------------------------------- -// buildPartials -// --------------------------------------------------------------------------- -// Append spectral peaks, extracted from a reassigned time-frequency -// spectrum, to eligible Partials, where possible. Peaks that cannot -// be used to extend eliglble Partials spawn new Partials. -// -// This is similar to the basic MQ partial formation strategy, except that -// before matching, all frequencies are normalized by the value of the -// warping envelope at the time of the current frame. This means that -// the frequency envelopes of all the Partials are warped, and need to -// be un-normalized by calling finishBuilding at the end of the building -// process. -// -void -PartialBuilder::buildPartials( Peaks & peaks, double frameTime ) -{ - mNewlyEligible.clear(); - - unsigned int matchCount = 0; // for debugging - - // frequency-sort the spectral peaks: - // (the eligible partials are always sorted by - // increasing frequency if we always sort the - // peaks this way) - std::sort( peaks.begin(), peaks.end(), SpectralPeak::sort_increasing_freq ); - - PartialPtrs::iterator eligible = mEligiblePartials.begin(); - for ( Peaks::iterator bpIter = peaks.begin(); bpIter != peaks.end(); ++bpIter ) - { - //const Breakpoint & bp = bpIter->breakpoint; - const double peakTime = frameTime + bpIter->time(); - - // find the Partial that is nearest in frequency to the Peak: - PartialPtrs::iterator nextEligible = eligible; - if ( eligible != mEligiblePartials.end() && - end_frequency( **eligible ) < bpIter->frequency() ) - { - ++nextEligible; - while ( nextEligible != mEligiblePartials.end() && - end_frequency( **nextEligible ) < bpIter->frequency() ) - { - ++nextEligible; - ++eligible; - } - - if ( nextEligible != mEligiblePartials.end() && - better_match( **nextEligible, **eligible, *bpIter ) ) - { - eligible = nextEligible; - } - } - - // INVARIANT: - // - // eligible is the position of the nearest (in frequency) - // eligible Partial (pointer) or it is mEligiblePartials.end(). - // - // nextEligible is the eligible Partial with frequency - // greater than bp, or it is mEligiblePartials.end(). - -#if defined(Debug_Loris) && Debug_Loris - /* - if ( nextEligible != mEligiblePartials.end() ) - { - debugger << matchFrequency << "( " << end_frequency( **eligible ) - << ", " << end_frequency( **nextEligible ) << ")" << endl; - } - */ -#endif - - // create a new Partial if there is no eligible Partial, - // or the frequency difference to the eligible Partial is - // too great, or the next peak is a better match for the - // eligible Partial, otherwise add this peak to the eligible - // Partial: - Peaks::iterator nextPeak = //Peaks::iterator( bpIter ); ++nextPeak; - ++Peaks::iterator( bpIter ); // some compilers choke on this? - - // decide whether this match should be made: - // - can only make the match if eligible is not the end of the list - // - the match is only good if it is close enough in frequency - // - even if the match is good, only match if the next one is not better - bool makeMatch = false; - if ( eligible != mEligiblePartials.end() ) - { - bool matchIsGood = mFreqDrift > - std::fabs( end_frequency( **eligible ) - bpIter->frequency() ); - if ( matchIsGood ) - { - bool nextIsBetter = ( nextPeak != peaks.end() && - better_match( **eligible, *nextPeak, *bpIter ) ); - if ( ! nextIsBetter ) - { - makeMatch = true; - } - } - } - - Breakpoint bp = bpIter->createBreakpoint(); - - if ( makeMatch ) - { - // invariant: - // if makeMatch is true, then eligible is the position of a valid Partial - (*eligible)->insert( peakTime, bp ); - mNewlyEligible.push_back( *eligible ); - - ++matchCount; - } - else - { - Partial p; - p.insert( peakTime, bp ); - mCollectedPartials.push_back( p ); - mNewlyEligible.push_back( & mCollectedPartials.back() ); - } - - // update eligible, nextEligible is the eligible Partial - // with frequency greater than bp, or it is mEligiblePartials.end(): - eligible = nextEligible; - } - - mEligiblePartials = mNewlyEligible; - - /* - debugger << "PartialBuilder::buildPartials: matched " << matchCount << endl; - debugger << "PartialBuilder::buildPartials: " << mNewlyEligible.size() << " newly eligible partials" << endl; - */ -} - -// --------------------------------------------------------------------------- -// finishBuilding -// --------------------------------------------------------------------------- -// Un-do the frequency warping performed in buildPartials, and return -// the Partials that were built. After calling finishBuilding, the -// builder is returned to its initial state, and ready to build another -// set of Partials. Partials are returned by appending them to the -// supplied PartialList. -// -void -PartialBuilder::finishBuilding( PartialList & product ) -{ - // append the collected Partials to the product list: - product.splice( product.end(), mCollectedPartials ); - - // reset the builder state: - mEligiblePartials.clear(); - mNewlyEligible.clear(); -} - - - -} // end of namespace Loris diff --git a/loris_library/Source/src/PartialBuilder.h b/loris_library/Source/src/PartialBuilder.h deleted file mode 100644 index 2592ffc..0000000 --- a/loris_library/Source/src/PartialBuilder.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef INCLUDE_PARTIALBUILDER_H -#define INCLUDE_PARTIALBUILDER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PartialBuilder.h - * - * Implementation of a class representing a policy for connecting peaks - * extracted from a reassigned time-frequency spectrum to form ridges - * and construct Partials. - * - * This strategy attemps to follow a reference frequency envelope when - * forming Partials, by prewarping all peak frequencies according to the - * (inverse of) frequency reference envelope. At the end of the analysis, - * Partial frequencies need to be un-warped by calling fixPartialFrequencies(). - * - * Kelly Fitz, 28 May 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Partial.h" -#include "PartialList.h" -#include "PartialPtrs.h" -#include "SpectralPeaks.h" - -#include - -// begin namespace -namespace Loris { - -class Envelope; - -// --------------------------------------------------------------------------- -// class PartialBuilder -// -// A class representing the process of connecting peaks (ridges) on a -// reassigned time-frequency surface to form Partials. -// -class PartialBuilder -{ -// --- public interface --- - -public: - - // constructor - // - // Construct a new builder that constrains Partial frequnecy - // drift by the specified drift value in Hz. - PartialBuilder( double drift ); - - // constructor - // - // Construct a new builder that constrains Partial frequnecy - // drift by the specified drift value in Hz. The frequency - // warping envelope is applied to the spectral peak frequencies - // and the frequency drift parameter in each frame before peaks - // are linked to eligible Partials. All the Partial frequencies - // need to be un-warped at the ned of the building process, by - // calling finishBuilding(). - PartialBuilder( double drift, const Envelope & freqWarpEnv ); - - // buildPartials - // - // Append spectral peaks, extracted from a reassigned time-frequency - // spectrum, to eligible Partials, where possible. Peaks that cannot - // be used to extend eliglble Partials spawn new Partials. - // - // This is similar to the basic MQ partial formation strategy, except that - // before matching, all frequencies are normalized by the value of the - // warping envelope at the time of the current frame. This means that - // the frequency envelopes of all the Partials are warped, and need to - // be un-normalized by calling finishBuilding at the end of the building - // process. - void buildPartials( Peaks & peaks, double frameTime ); - - // finishBuilding - // - // Un-do the frequency warping performed in buildPartials, and return - // the Partials that were built. After calling finishBuilding, the - // builder is returned to its initial state, and ready to build another - // set of Partials. Partials are returned by appending them to the - // supplied PartialList. - void finishBuilding( PartialList & product ); - -private: - -// --- auxiliary member functions --- - - double freq_distance( const Partial & partial, const SpectralPeak & pk ); - - bool better_match( const Partial & part, const SpectralPeak & pk1, - const SpectralPeak & pk2 ); - bool better_match( const Partial & part1, - const Partial & part2, const SpectralPeak & pk ); - - -// --- collected partials --- - - PartialList mCollectedPartials; // collect partials here - -// --- builder state variables --- - - PartialPtrs mEligiblePartials; - PartialPtrs mNewlyEligible; // keep track of eligible partials here - -// --- parameters --- - - std::auto_ptr< Envelope > mFreqWarping; // reference envelope - - double mFreqDrift; - -// --- disallow copy and assignment --- - - PartialBuilder( const PartialBuilder & ); - PartialBuilder& operator=( const PartialBuilder & ); - -}; // end of class PartialBuilder - -} // end of namespace Loris - -#endif /* ndef INCLUDE_PARTIALBUILDER_H */ diff --git a/loris_library/Source/src/PartialList.h b/loris_library/Source/src/PartialList.h deleted file mode 100644 index ca91509..0000000 --- a/loris_library/Source/src/PartialList.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef INCLUDE_PARTIALLIST_H -#define INCLUDE_PARTIALLIST_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PartialList.h - * - * Type definition of Loris::PartialList, which is just a name - * for std::list< Loris::Partial >. - * - * Kelly Fitz, 6 March 2002 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -// Seems like we shouldn't need to include Partial.h, but -// without it, I can't instantiate a PartialList. I need -// a definition of Partial for PartialList to be unambiguous. -#include "Partial.h" -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class PartialList -// -// PartialList is a typedef for a std::list<> of Loris Partials. The -// oscciated bidirectional iterators are also defined as -// PartialListIterator and PartialListConstIterator. Since these are -// simply typedefs, they classes have identical interfaces to std::list, -// std::list::iterator, and std::list::const_iterator, respectively. -// -typedef std::list< Loris::Partial > PartialList; -typedef std::list< Loris::Partial >::iterator PartialListIterator; -typedef std::list< Loris::Partial >::const_iterator PartialListConstIterator; - -} // end of namespace Loris - -#endif /* ndef INCLUDE_PARTIALLIST_H */ diff --git a/loris_library/Source/src/PartialPtrs.h b/loris_library/Source/src/PartialPtrs.h deleted file mode 100644 index a773aec..0000000 --- a/loris_library/Source/src/PartialPtrs.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef INCLUDE_PARTIALPTRS_H -#define INCLUDE_PARTIALPTRS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PartialPtrs.h - * - * Type definition of Loris::PartialPtrs. - * - * PartialPtrs is a collection of pointers to Partials that - * can be used (among other things) for algorithms that operate - * on a range of Partials, but don't rely on access to their - * container. - * - * Kelly Fitz, 23 May 2002 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Partial.h" -#include -#include - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// class PartialPtrs -// -// PartialPtrs is a typedef for a std::vectror<> of pointers to Loris -// Partials. The oscciated bidirectional iterators are also defined as -// PartialPtrsIterator and PartialPtrsConstIterator. Since these are -// simply typedefs, they classes have identical interfaces to -// std::vector, std::vector::iterator, and std::vector::const_iterator, -// respectively. -// -// PartialPtrs is a collection of pointers to Partials that can be used -// (among other things) for algorithms that operate on a range of -// Partials, but don't rely on access to their container. A template -// function defined in a header file can convert a range of Partials to a -// PartialPtrs using the template free function fillPartialPtrs() (see -// below), and pass the latter to the algorithm implementation, thereby -// generalizing access to the algorithm across containers without -// exposing the implementation in the header file. -// -typedef std::vector< Partial * > PartialPtrs; -typedef std::vector< Partial * >::iterator PartialPtrsIterator; -typedef std::vector< Partial * >::const_iterator PartialPtrsConstIterator; - -typedef std::vector< const Partial * > ConstPartialPtrs; -typedef std::vector< const Partial * >::iterator ConstPartialPtrsIterator; -typedef std::vector< const Partial * >::const_iterator ConstPartialPtrsConstIterator; - - -// --------------------------------------------------------------------------- -// fillPartialPtrs -// --------------------------------------------------------------------------- -// Fill the specified PartialPtrs with pointers to the Partials n the -// specified half-open (STL-style) range. This is a generally useful -// operation that can be used to adapt algorithms to work with arbitrary -// containers of Partials without exposing the algorithms themselves in -// the header files. -// -template -void fillPartialPtrs( Iter begin, Iter end, PartialPtrs & fillme ) -{ - fillme.reserve( std::distance( begin, end ) ); - fillme.clear(); - while ( begin != end ) - fillme.push_back( &(*begin++) ); -} - -template -void fillPartialPtrs( Iter begin, Iter end, ConstPartialPtrs & fillme ) -{ - fillme.reserve( std::distance( begin, end ) ); - fillme.clear(); - while ( begin != end ) - fillme.push_back( &(*begin++) ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_PARTIALPTRS_H */ diff --git a/loris_library/Source/src/PartialUtils.cpp b/loris_library/Source/src/PartialUtils.cpp deleted file mode 100644 index 6152e09..0000000 --- a/loris_library/Source/src/PartialUtils.cpp +++ /dev/null @@ -1,603 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PartialUtils.C - * - * A group of Partial utility function objects for use with STL - * searching and sorting algorithms. PartialUtils is a namespace - * within the Loris namespace. - * - * Kelly Fitz, 17 June 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "PartialUtils.h" - -#include "Breakpoint.h" -#include "BreakpointEnvelope.h" -#include "BreakpointUtils.h" -#include "Envelope.h" -#include "Partial.h" - -#include "phasefix.h" - -#include -#include -#include -#include - -// begin namespace -namespace Loris { - -namespace PartialUtils { - - -// -- base class -- - -// --------------------------------------------------------------------------- -// PartialMutator constructor from double -// --------------------------------------------------------------------------- -PartialMutator::PartialMutator( double x ) : - env( new BreakpointEnvelope( x ) ) -{ -} - -// --------------------------------------------------------------------------- -// PartialMutator constructor from envelope -// --------------------------------------------------------------------------- -PartialMutator::PartialMutator( const Envelope & e ) : - env( e.clone() ) -{ -} - -// --------------------------------------------------------------------------- -// PartialMutator copy constructor -// --------------------------------------------------------------------------- -PartialMutator::PartialMutator( const PartialMutator & rhs ) : - env( rhs.env->clone() ) -{ -} - -// --------------------------------------------------------------------------- -// PartialMutator destructor -// --------------------------------------------------------------------------- -PartialMutator::~PartialMutator( void ) -{ - delete env; -} - -// --------------------------------------------------------------------------- -// PartialMutator assignment operator -// --------------------------------------------------------------------------- -PartialMutator & -PartialMutator::operator=( const PartialMutator & rhs ) -{ - if ( this != &rhs ) - { - delete env; - env = rhs.env->clone(); - } - return *this; -} - -// -- amplitude scaling -- - -// --------------------------------------------------------------------------- -// AmplitudeScaler function call operator -// --------------------------------------------------------------------------- -// Scale the amplitude of the specified Partial according to -// an envelope representing a time-varying amplitude scale value. -// -void -AmplitudeScaler::operator()( Partial & p ) const -{ - for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) - { - pos.breakpoint().setAmplitude( pos.breakpoint().amplitude() * - env->valueAt( pos.time() ) ); - } -} - -// --------------------------------------------------------------------------- -// BandwidthScaler function call operator -// --------------------------------------------------------------------------- -// Scale the bandwidth of the specified Partial according to -// an envelope representing a time-varying bandwidth scale value. -// -void -BandwidthScaler::operator()( Partial & p ) const -{ - for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) - { - pos.breakpoint().setBandwidth( pos.breakpoint().bandwidth() * - env->valueAt( pos.time() ) ); - } -} - -// --------------------------------------------------------------------------- -// BandwidthSetter function call operator -// --------------------------------------------------------------------------- -// Set the bandwidth of the specified Partial according to -// an envelope representing a time-varying bandwidth value. -// -void -BandwidthSetter::operator()( Partial & p ) const -{ - for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) - { - pos.breakpoint().setBandwidth( env->valueAt( pos.time() ) ); - } -} - -// --------------------------------------------------------------------------- -// FrequencyScaler function call operator -// --------------------------------------------------------------------------- -// Scale the frequency of the specified Partial according to -// an envelope representing a time-varying frequency scale value. -// -void -FrequencyScaler::operator()( Partial & p ) const -{ - for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) - { - pos.breakpoint().setFrequency( pos.breakpoint().frequency() * - env->valueAt( pos.time() ) ); - } -} - -// --------------------------------------------------------------------------- -// NoiseRatioScaler function call operator -// --------------------------------------------------------------------------- -// Scale the relative noise content of the specified Partial according -// to an envelope representing a (time-varying) noise energy -// scale value. -// -void -NoiseRatioScaler::operator()( Partial & p ) const -{ - for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) - { - // compute new bandwidth value: - double bw = pos.breakpoint().bandwidth(); - if ( bw < 1. ) - { - double ratio = bw / (1. - bw); - ratio *= env->valueAt( pos.time() ); - bw = ratio / ( 1. + ratio ); - } - else - { - bw = 1.; - } - pos.breakpoint().setBandwidth( bw ); - } -} - -// --------------------------------------------------------------------------- -// PitchShifter function call operator -// --------------------------------------------------------------------------- -// Shift the pitch of the specified Partial according to -// the given pitch envelope. The pitch envelope is assumed to have -// units of cents (1/100 of a halfstep). -// -void -PitchShifter::operator()( Partial & p ) const -{ - for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) - { - // compute frequency scale: - double scale = - std::pow( 2., ( 0.01 * env->valueAt( pos.time() ) ) / 12. ); - pos.breakpoint().setFrequency( pos.breakpoint().frequency() * scale ); - } -} - -// --------------------------------------------------------------------------- -// Cropper function call operator -// --------------------------------------------------------------------------- -// Trim a Partial by removing Breakpoints outside a specified time span. -// Insert a Breakpoint at the boundary when cropping occurs. -// -void -Cropper::operator()( Partial & p ) const -{ - // crop beginning of Partial - Partial::iterator it = p.findAfter( minTime ); - if ( it != p.begin() ) // Partial begins earlier than minTime - { - if ( it != p.end() ) // Partial ends later than minTime - { - Breakpoint bp = p.parametersAt( minTime ); - it = p.insert( minTime, bp ); - } - it = p.erase( p.begin(), it ); - } - - // crop end of Partial - it = p.findAfter( maxTime ); - if ( it != p.end() ) // Partial ends later than maxTime - { - if ( it != p.begin() ) // Partial begins earlier than maxTime - { - Breakpoint bp = p.parametersAt( maxTime ); - it = p.insert( maxTime, bp ); - ++it; // advance, we don't want to cut this one off - } - it = p.erase( it, p.end() ); - } -} - -// --------------------------------------------------------------------------- -// TimeShifter function call operator -// --------------------------------------------------------------------------- -// Shift the time of all the Breakpoints in a Partial by a constant amount. -// -void -TimeShifter::operator()( Partial & p ) const -{ - // Since the Breakpoint times are immutable, the only way to - // shift the Partial in time is to construct a new Partial and - // assign it to the argument p. - Partial result; - result.setLabel( p.label() ); - - for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) - { - result.insert( pos.time() + offset, pos.breakpoint() ); - } - p = result; -} - -// --------------------------------------------------------------------------- -// peakAmplitude -// --------------------------------------------------------------------------- -//! Return the maximum amplitude achieved by a partial. -//! -//! \param p is the Partial to evaluate -//! \return the maximum (absolute) amplitude achieved by -//! the partial p -// -double peakAmplitude( const Partial & p ) -{ - double peak = 0; - for ( Partial::const_iterator it = p.begin(); - it != p.end(); - ++it ) - { - peak = std::max( peak, it->amplitude() ); - } - return peak; -} - -// --------------------------------------------------------------------------- -// avgAmplitude -// --------------------------------------------------------------------------- -//! Return the average amplitude over all Breakpoints in this Partial. -//! Return zero if the Partial has no Breakpoints. -//! -//! \param p is the Partial to evaluate -//! \return the average amplitude of Breakpoints in the Partial p -// -double avgAmplitude( const Partial & p ) -{ - double avg = 0; - for ( Partial::const_iterator it = p.begin(); - it != p.end(); - ++it ) - { - avg += it->amplitude(); - } - - if ( avg != 0 ) - { - avg /= p.numBreakpoints(); - } - - return avg; -} - - -// --------------------------------------------------------------------------- -// avgFrequency -// --------------------------------------------------------------------------- -//! Return the average frequency over all Breakpoints in this Partial. -//! Return zero if the Partial has no Breakpoints. -//! -//! \param p is the Partial to evaluate -//! \return the average frequency (Hz) of Breakpoints in the Partial p -// -double avgFrequency( const Partial & p ) -{ - double avg = 0; - for ( Partial::const_iterator it = p.begin(); - it != p.end(); - ++it ) - { - avg += it->frequency(); - } - - if ( avg != 0 ) - { - avg /= p.numBreakpoints(); - } - - return avg; -} - - -// --------------------------------------------------------------------------- -// weightedAvgFrequency -// --------------------------------------------------------------------------- -//! Return the average frequency over all Breakpoints in this Partial, -//! weighted by the Breakpoint amplitudes. -//! Return zero if the Partial has no Breakpoints. -//! -//! \param p is the Partial to evaluate -//! \return the average frequency (Hz) of Breakpoints in the Partial p -// -double weightedAvgFrequency( const Partial & p ) -{ - double avg = 0; - double ampsum = 0; - for ( Partial::const_iterator it = p.begin(); - it != p.end(); - ++it ) - { - avg += it->amplitude() * it->frequency(); - ampsum += it->amplitude(); - } - - if ( avg != 0 && ampsum != 0 ) - { - avg /= ampsum; - } - else - { - avg = 0; - } - - return avg; -} - -// -- phase maintenance functions -- - -// --------------------------------------------------------------------------- -// fixPhaseBefore -// -//! Recompute phases of all Breakpoints earlier than the specified time -//! so that the synthesize phases of those earlier Breakpoints matches -//! the stored phase, and the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the Partial -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the Partial. -//! -//! \param p The Partial whose phases should be fixed. -//! \param t The time before which phases should be adjusted. -// -void fixPhaseBefore( Partial & p, double t ) -{ - if ( 1 < p.numBreakpoints() ) - { - Partial::iterator pos = p.findNearest( t ); - Assert( pos != p.end() ); - - fixPhaseBackward( p.begin(), pos ); - } -} - -// --------------------------------------------------------------------------- -// fixPhaseAfter -// -//! Recompute phases of all Breakpoints later than the specified time -//! so that the synthesize phases of those later Breakpoints matches -//! the stored phase, as long as the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is simply left unmodified, -//! and future phases wil be recomputed from that one. -//! -//! \param p The Partial whose phases should be fixed. -//! \param t The time after which phases should be adjusted. -// -void fixPhaseAfter( Partial & p, double t ) -{ - // nothing to do it there are not at least - // two Breakpoints in the Partial - if ( 1 < p.numBreakpoints() ) - { - Partial::iterator pos = p.findNearest( t ); - Assert( pos != p.end() ); - - fixPhaseForward( pos, --p.end() ); - } -} - -// --------------------------------------------------------------------------- -// fixPhaseForward -// -//! Recompute phases of all Breakpoints later than the specified time -//! so that the synthesize phases of those later Breakpoints matches -//! the stored phase, as long as the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. Breakpoints later than -//! tend are unmodified. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is simply left unmodified, -//! and future phases wil be recomputed from that one. -//! -//! HEY Is this interesting, in general? Why would you want to do this? -//! -//! \param p The Partial whose phases should be fixed. -//! \param tbeg The phases and frequencies of Breakpoints later than the -//! one nearest this time will be modified. -//! \param tend The phases and frequencies of Breakpoints earlier than the -//! one nearest this time will be modified. Should be greater -//! than tbeg, or else they will be swapped. -// -void fixPhaseForward( Partial & p, double tbeg, double tend ) -{ - if ( tbeg > tend ) - { - std::swap( tbeg, tend ); - } - - // nothing to do it there are not at least - // two Breakpoints in the Partial - if ( 1 < p.numBreakpoints() ) - { - // find the positions nearest tbeg and tend - Partial::iterator posbeg = p.findNearest( tbeg ); - Partial::iterator posend = p.findNearest( tend ); - - // if the positions are different, and tend is - // the end, back it up - if ( posbeg != posend && posend == p.end() ) - { - --posend; - } - fixPhaseForward( posbeg, posend ); - } -} - -// --------------------------------------------------------------------------- -// fixPhaseAt -// -//! Recompute phases of all Breakpoints in a Partial -//! so that the synthesize phases match the stored phases, -//! and the synthesized phase at (nearest) the specified -//! time matches the stored (not recomputed) phase. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the Partial -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the Partial. Forward phase fixing is only applied -//! to non-null (nonzero-amplitude) Breakpoints. If a null is encountered, -//! its phase is simply left unmodified, and future phases wil be -//! recomputed from that one. -//! -//! \param p The Partial whose phases should be fixed. -//! \param t The time at which phases should be made correct. -// -void fixPhaseAt( Partial & p, double t ) -{ - if ( 1 < p.numBreakpoints() ) - { - Partial::iterator pos = p.findNearest( t ); - Assert( pos != p.end() ); - - fixPhaseForward( pos, --p.end() ); - fixPhaseBackward( p.begin(), pos ); - } -} - -// --------------------------------------------------------------------------- -// fixPhaseBetween -// -//! Fix the phase travel between two times by adjusting the -//! frequency and phase of Breakpoints between those two times. -//! -//! This algorithm assumes that there is nothing interesting about the -//! phases of the intervening Breakpoints, and modifies their frequencies -//! as little as possible to achieve the correct amount of phase travel -//! such that the frequencies and phases at the specified times -//! match the stored values. The phases of all the Breakpoints between -//! the specified times are recomputed. -//! -//! THIS DOES NOT YET TREAT NULL BREAKPOINTS DIFFERENTLY FROM OTHERS. -//! -//! \pre There must be at least one Breakpoint in the -//! Partial between the specified times tbeg and tend. -//! \post The phases and frequencies of the Breakpoints in the -//! range have been recomputed such that an oscillator -//! initialized to the parameters of the first Breakpoint -//! will arrive at the parameters of the last Breakpoint, -//! and all the intervening Breakpoints will be matched. -//! \param p The partial whose phases and frequencies will be recomputed. -//! The Breakpoint at this position is unaltered. -//! \param tbeg The phases and frequencies of Breakpoints later than the -//! one nearest this time will be modified. -//! \param tend The phases and frequencies of Breakpoints earlier than the -//! one nearest this time will be modified. Should be greater -//! than tbeg, or else they will be swapped. -// -void fixPhaseBetween( Partial & p, double tbeg, double tend ) -{ - if ( tbeg > tend ) - { - std::swap( tbeg, tend ); - } - - // for Partials that do not extend over the entire - // specified time range, just recompute phases from - // beginning or end of the range: - if ( p.endTime() < tend ) - { - // OK if start time is also after tbeg, will - // just recompute phases from start of p. - fixPhaseAfter( p, tbeg ); - } - else if ( p.startTime() > tbeg ) - { - fixPhaseBefore( p, tend ); - } - else - { - // invariant: - // p begins before tbeg and ends after tend. - Partial::iterator b = p.findNearest( tbeg ); - Partial::iterator e = p.findNearest( tend ); - - // if there is a null Breakpoint n between b and e, then - // should fix forward from b to n, and backward from - // e to n. Otherwise, do this complicated thing. - Partial::iterator nullbp = std::find_if( b, e, BreakpointUtils::isNull ); - if ( nullbp != e ) - { - fixPhaseForward( b, nullbp ); - fixPhaseBackward( nullbp, e ); - } - else - { - fixPhaseBetween( b, e ); - } - } -} - -} // end of namespace PartialUtils - -} // end of namespace Loris - diff --git a/loris_library/Source/src/PartialUtils.h b/loris_library/Source/src/PartialUtils.h deleted file mode 100644 index 4dc4c74..0000000 --- a/loris_library/Source/src/PartialUtils.h +++ /dev/null @@ -1,1190 +0,0 @@ -#ifndef INCLUDE_PARTIALUTILS_H -#define INCLUDE_PARTIALUTILS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PartialUtils.h - * - * A group of Partial utility function objects for use with STL - * searching and sorting algorithms. PartialUtils is a namespace - * within the Loris namespace. - * - * This file defines three kinds of functors: - * - Partial mutators - * - predicates on Partials - * - Partial comparitors - * - * Kelly Fitz, 6 July 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Envelope.h" -#include "Partial.h" - -#include -#include -#include - -// begin namespace -namespace Loris { - -namespace PartialUtils { - -// -- Partial mutating functors -- - -// --------------------------------------------------------------------------- -// PartialMutator -// -//! PartialMutator is an abstract base class for Partial mutators, -//! functors that operate on Partials according to a time-varying -//! envelope. The base class manages a polymorphic Envelope instance -//! that provides the time-varying mutation parameters. -//! -//! \invariant env is a non-zero pointer to a valid instance of a -//! class derived from the abstract class Envelope. -class PartialMutator : public std::unary_function< Partial, void > -{ -public: - - //! Construct a new PartialMutator from a constant mutation factor. - PartialMutator( double x ); - - //! Construct a new PartialMutator from an Envelope representing - //! a time-varying mutation factor. - PartialMutator( const Envelope & e ); - - //! Construct a new PartialMutator that is a copy of another. - PartialMutator( const PartialMutator & rhs ); - - //! Destroy this PartialMutator, deleting its Envelope. - virtual ~PartialMutator( void ); - - //! Make this PartialMutator a duplicate of another one. - //! - //! \param rhs is the PartialMutator to copy. - PartialMutator & operator=( const PartialMutator & rhs ); - - //! Function call operator: apply a mutation factor to the - //! specified Partial. Derived classes must implement this - //! member. - virtual void operator()( Partial & p ) const = 0; - -protected: - - //! pointer to an envelope that governs the - //! time-varying mutation - Envelope * env; -}; - -// --------------------------------------------------------------------------- -// AmplitudeScaler -// -//! Scale the amplitude of the specified Partial according to -//! an envelope representing a time-varying amplitude scale value. -// -class AmplitudeScaler : public PartialMutator -{ -public: - - //! Construct a new AmplitudeScaler from a constant scale factor. - AmplitudeScaler( double x ) : PartialMutator( x ) {} - - //! Construct a new AmplitudeScaler from an Envelope representing - //! a time-varying scale factor. - AmplitudeScaler( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: apply a scale factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// scaleAmplitude -// --------------------------------------------------------------------------- -//! Scale the amplitude of the specified Partial according to -//! an envelope representing a amplitude scale value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Arg > -void scaleAmplitude( Partial & p, const Arg & arg ) -{ - AmplitudeScaler scaler( arg ); - scaler( p ); -} - -// --------------------------------------------------------------------------- -// scaleAmplitude -// --------------------------------------------------------------------------- -//! Scale the amplitude of a sequence of Partials according to -//! an envelope representing a amplitude scale value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Iter, class Arg > -void scaleAmplitude( Iter b, Iter e, const Arg & arg ) -{ - AmplitudeScaler scaler( arg ); - while ( b != e ) - { - scaler( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// BandwidthScaler -// -//! Scale the bandwidth of the specified Partial according to -//! an envelope representing a time-varying bandwidth scale value. -// -class BandwidthScaler : public PartialMutator -{ -public: - - //! Construct a new BandwidthScaler from a constant scale factor. - BandwidthScaler( double x ) : PartialMutator( x ) {} - - //! Construct a new BandwidthScaler from an Envelope representing - //! a time-varying scale factor. - BandwidthScaler( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: apply a scale factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// scaleBandwidth -// --------------------------------------------------------------------------- -//! Scale the bandwidth of the specified Partial according to -//! an envelope representing a amplitude scale value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Arg > -void scaleBandwidth( Partial & p, const Arg & arg ) -{ - BandwidthScaler scaler( arg ); - scaler( p ); -} - -// --------------------------------------------------------------------------- -// scaleBandwidth -// --------------------------------------------------------------------------- -//! Scale the bandwidth of a sequence of Partials according to -//! an envelope representing a bandwidth scale value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Iter, class Arg > -void scaleBandwidth( Iter b, Iter e, const Arg & arg ) -{ - BandwidthScaler scaler( arg ); - while ( b != e ) - { - scaler( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// BandwidthSetter -// -//! Set the bandwidth of the specified Partial according to -//! an envelope representing a time-varying bandwidth value. -// -class BandwidthSetter : public PartialMutator -{ -public: - - //! Construct a new BandwidthSetter from a constant bw factor. - BandwidthSetter( double x ) : PartialMutator( x ) {} - - //! Construct a new BandwidthSetter from an Envelope representing - //! a time-varying bw factor. - BandwidthSetter( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: assign a bw factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// setBandwidth -// --------------------------------------------------------------------------- -//! Set the bandwidth of the specified Partial according to -//! an envelope representing a amplitude scale value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying bw factor. -// -template< class Arg > -void setBandwidth( Partial & p, const Arg & arg ) -{ - BandwidthSetter setter( arg ); - setter( p ); -} - -// --------------------------------------------------------------------------- -// setBandwidth -// --------------------------------------------------------------------------- -//! Set the bandwidth of a sequence of Partials according to -//! an envelope representing a bandwidth value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Iter, class Arg > -void setBandwidth( Iter b, Iter e, const Arg & arg ) -{ - BandwidthSetter setter( arg ); - while ( b != e ) - { - setter( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// FrequencyScaler -// -//! Scale the frequency of the specified Partial according to -//! an envelope representing a time-varying bandwidth scale value. -// -class FrequencyScaler : public PartialMutator -{ -public: - - //! Construct a new FrequencyScaler from a constant scale factor. - FrequencyScaler( double x ) : PartialMutator( x ) {} - - //! Construct a new FrequencyScaler from an Envelope representing - //! a time-varying scale factor. - FrequencyScaler( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: apply a scale factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// scaleFrequency -// --------------------------------------------------------------------------- -//! Scale the frequency of the specified Partial according to -//! an envelope representing a frequency scale value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Arg > -void scaleFrequency( Partial & p, const Arg & arg ) -{ - FrequencyScaler scaler( arg ); - scaler( p ); -} - -// --------------------------------------------------------------------------- -// scaleFrequency -// --------------------------------------------------------------------------- -//! Scale the frequency of a sequence of Partials according to -//! an envelope representing a frequency scale value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Iter, class Arg > -void scaleFrequency( Iter b, Iter e, const Arg & arg ) -{ - FrequencyScaler scaler( arg ); - while ( b != e ) - { - scaler( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// NoiseRatioScaler -// -//! Scale the relative noise content of the specified Partial according -//! to an envelope representing a time-varying bandwidth scale value. -// -class NoiseRatioScaler : public PartialMutator -{ -public: - - //! Construct a new NoiseRatioScaler from a constant scale factor. - NoiseRatioScaler( double x ) : PartialMutator( x ) {} - - //! Construct a new NoiseRatioScaler from an Envelope representing - //! a time-varying scale factor. - NoiseRatioScaler( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: apply a scale factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// scaleNoiseRatio -// --------------------------------------------------------------------------- -//! Scale the relative noise content of the specified Partial according to -//! an envelope representing a scale value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Arg > -void scaleNoiseRatio( Partial & p, const Arg & arg ) -{ - NoiseRatioScaler scaler( arg ); - scaler( p ); -} - -// --------------------------------------------------------------------------- -// scaleNoiseRatio -// --------------------------------------------------------------------------- -//! Scale the relative noise content of a sequence of Partials according to -//! an envelope representing a scale value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant scale factor or an Envelope -//! describing the time-varying scale factor. -// -template< class Iter, class Arg > -void scaleNoiseRatio( Iter b, Iter e, const Arg & arg ) -{ - NoiseRatioScaler scaler( arg ); - while ( b != e ) - { - scaler( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// PitchShifter -// -//! Shift the pitch of the specified Partial according to -//! the given pitch envelope. The pitch envelope is assumed to have -//! units of cents (1/100 of a halfstep). -// -class PitchShifter : public PartialMutator -{ -public: - - //! Construct a new PitchShifter from a constant scale factor. - PitchShifter( double x ) : PartialMutator( x ) {} - - //! Construct a new PitchShifter from an Envelope representing - //! a time-varying scale factor. - PitchShifter( const Envelope & e ) : PartialMutator( e ) {} - - //! Function call operator: apply a scale factor to the specified - //! Partial. - void operator()( Partial & p ) const; -}; - -// --------------------------------------------------------------------------- -// shiftPitch -// --------------------------------------------------------------------------- -//! Shift the pitch of the specified Partial according to -//! an envelope representing a pitch value or envelope. -//! -//! \param p is a Partial to mutate. -//! \param arg is either a constant pitch factor or an Envelope -//! describing the time-varying pitch factor in cents (1/100 of a -//! halfstep). -// -template< class Arg > -void shiftPitch( Partial & p, const Arg & arg ) -{ - PitchShifter shifter( arg ); - shifter( p ); -} - -// --------------------------------------------------------------------------- -// shiftPitch -// --------------------------------------------------------------------------- -//! Shift the pitch of a sequence of Partials according to -//! an envelope representing a pitch value or envelope. -//! -//! \param b is the beginning of a sequence of Partials to mutate. -//! \param e is the end of a sequence of Partials to mutate. -//! \param arg is either a constant pitch factor or an Envelope -//! describing the time-varying pitch factor in cents (1/100 of a -//! halfstep). -// -template< class Iter, class Arg > -void shiftPitch( Iter b, Iter e, const Arg & arg ) -{ - PitchShifter shifter( arg ); - while ( b != e ) - { - shifter( *b++ ); - } -} - -// These ones are not derived from PartialMutator, because -// they don't use an Envelope and cannot be time-varying. - -// --------------------------------------------------------------------------- -// Cropper -// -//! Trim a Partial by removing Breakpoints outside a specified time span. -//! Insert a Breakpoint at the boundary when cropping occurs. -class Cropper -{ -public: - - //! Construct a new Cropper from a pair of times (in seconds) - //! representing the span of time to which Partials should be - //! cropped. - Cropper( double t1, double t2 ) : - minTime( std::min( t1, t2 ) ), - maxTime( std::max( t1, t2 ) ) - { - } - - //! Function call operator: crop the specified Partial. - //! Trim a Partial by removing Breakpoints outside the span offset - //! [minTime, maxTime]. Insert a Breakpoint at the boundary when - //! cropping occurs. - void operator()( Partial & p ) const; - -private: - double minTime, maxTime; -}; - -// --------------------------------------------------------------------------- -// crop -// --------------------------------------------------------------------------- -//! Trim a Partial by removing Breakpoints outside a specified time span. -//! Insert a Breakpoint at the boundary when cropping occurs. -//! -//! This operation may leave the Partial empty, if it previously had -//! no Breakpoints in the span [t1,t2]. -//! -//! \param p is the Partial to crop. -//! \param t1 is the beginning of the time span to which the Partial -//! should be cropped. -//! \param t2 is the end of the time span to which the Partial -//! should be cropped. -// -inline -void crop( Partial & p, double t1, double t2 ) -{ - Cropper cropper( t1, t2 ); - cropper( p ); -} - -// --------------------------------------------------------------------------- -// crop -// --------------------------------------------------------------------------- -//! Trim a sequence of Partials by removing Breakpoints outside a specified -//! time span. Insert a Breakpoint at the boundary when cropping occurs. -//! -//! This operation may leave some empty Partials, if they previously had -//! no Breakpoints in the span [t1,t2]. -//! -//! \param b is the beginning of a sequence of Partials to crop. -//! \param e is the end of a sequence of Partials to crop. -//! \param t1 is the beginning of the time span to which the Partials -//! should be cropped. -//! \param t2 is the end of the time span to which the Partials -//! should be cropped. -// -template< class Iter > -void crop( Iter b, Iter e, double t1, double t2 ) -{ - Cropper cropper( t1, t2 ); - while ( b != e ) - { - cropper( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// TimeShifter -// -//! Shift the time of all the Breakpoints in a Partial by a -//! constant amount. -// -class TimeShifter -{ -public: - - //! Construct a new TimeShifter from a constant offset in seconds. - TimeShifter( double x ) : offset( x ) {} - - //! Function call operator: apply a time shift to the specified - //! Partial. - void operator()( Partial & p ) const; - -private: - double offset; -}; - -// --------------------------------------------------------------------------- -// shiftTime -// --------------------------------------------------------------------------- -//! Shift the time of all the Breakpoints in a Partial by a -//! constant amount. -//! -//! \param p is a Partial to shift. -//! \param offset is a constant offset in seconds. -// -inline -void shiftTime( Partial & p, double offset ) -{ - TimeShifter shifter( offset ); - shifter( p ); -} - -// --------------------------------------------------------------------------- -// shiftTime -// --------------------------------------------------------------------------- -//! Shift the time of all the Breakpoints in a Partial by a -//! constant amount. -//! -//! \param b is the beginning of a sequence of Partials to shift. -//! \param e is the end of a sequence of Partials to shift. -//! \param offset is a constant offset in seconds. -// -template< class Iter > -void shiftTime( Iter b, Iter e, double offset ) -{ - TimeShifter shifter( offset ); - while ( b != e ) - { - shifter( *b++ ); - } -} - -// --------------------------------------------------------------------------- -// timeSpan -// --------------------------------------------------------------------------- -//! Return the time (in seconds) spanned by a specified half-open -//! range of Partials as a std::pair composed of the earliest -//! Partial start time and latest Partial end time in the range. -// -template < typename Iterator > -std::pair< double, double > -timeSpan( Iterator begin, Iterator end ) -{ - double tmin = 0., tmax = 0.; - if ( begin != end ) - { - Iterator it = begin; - tmin = it->startTime(); - tmax = it->endTime(); - while( it != end ) - { - tmin = std::min( tmin, it->startTime() ); - tmax = std::max( tmax, it->endTime() ); - ++it; - } - } - return std::make_pair( tmin, tmax ); -} - -// --------------------------------------------------------------------------- -// peakAmplitude -// --------------------------------------------------------------------------- -//! Return the maximum amplitude achieved by a Partial. -//! -//! \param p is the Partial to evaluate -//! \return the maximum (absolute) amplitude achieved by -//! the partial p -// -double peakAmplitude( const Partial & p ); - -// --------------------------------------------------------------------------- -// avgAmplitude -// --------------------------------------------------------------------------- -//! Return the average amplitude over all Breakpoints in this Partial. -//! Return zero if the Partial has no Breakpoints. -//! -//! \param p is the Partial to evaluate -//! \return the average amplitude of Breakpoints in the Partial p -// -double avgAmplitude( const Partial & p ); - -// --------------------------------------------------------------------------- -// avgFrequency -// --------------------------------------------------------------------------- -//! Return the average frequency over all Breakpoints in this Partial. -//! Return zero if the Partial has no Breakpoints. -//! -//! \param p is the Partial to evaluate -//! \return the average frequency (Hz) of Breakpoints in the Partial p -// -double avgFrequency( const Partial & p ); - -// --------------------------------------------------------------------------- -// weightedAvgFrequency -// --------------------------------------------------------------------------- -//! Return the average frequency over all Breakpoints in this Partial, -//! weighted by the Breakpoint amplitudes. -//! Return zero if the Partial has no Breakpoints. -//! -//! \param p is the Partial to evaluate -//! \return the average frequency (Hz) of Breakpoints in the Partial p -// -double weightedAvgFrequency( const Partial & p ); - -// -- phase maintenance functions -- - -// --------------------------------------------------------------------------- -// fixPhaseBefore -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints earlier than the specified time -//! so that the synthesized phases of those earlier Breakpoints matches -//! the stored phase, and the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the Partial -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the Partial. -//! -//! \param p The Partial whose phases should be fixed. -//! \param t The time before which phases should be adjusted. -// -void fixPhaseBefore( Partial & p, double t ); - -// --------------------------------------------------------------------------- -// fixPhaseBefore (range) -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints earlier than the specified time -//! so that the synthesized phases of those earlier Breakpoints matches -//! the stored phase, and the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the Partial -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the Partial. -//! -//! \param b The beginning of a range of Partials whose phases -//! should be fixed. -//! \param e The end of a range of Partials whose phases -//! should be fixed. -//! \param t The time before which phases should be adjusted. -// -template < class Iter > -void fixPhaseBefore( Iter b, Iter e, double t ) -{ - while ( b != e ) - { - fixPhaseBefore( *b, t ); - ++b; - } -} - -// --------------------------------------------------------------------------- -// fixPhaseAfter -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints later than the specified time -//! so that the synthesized phases of those later Breakpoints matches -//! the stored phase, as long as the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is simply left unmodified, -//! and future phases wil be recomputed from that one. -//! -//! \param p The Partial whose phases should be fixed. -//! \param t The time after which phases should be adjusted. -// -void fixPhaseAfter( Partial & p, double t ); - -// --------------------------------------------------------------------------- -// fixPhaseAfter (range) -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints later than the specified time -//! so that the synthesized phases of those later Breakpoints matches -//! the stored phase, as long as the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is simply left unmodified, -//! and future phases wil be recomputed from that one. -//! -//! \param b The beginning of a range of Partials whose phases -//! should be fixed. -//! \param e The end of a range of Partials whose phases -//! should be fixed. -//! \param t The time after which phases should be adjusted. -// -template < class Iter > -void fixPhaseAfter( Iter b, Iter e, double t ) -{ - while ( b != e ) - { - fixPhaseAfter( *b, t ); - ++b; - } -} - -// --------------------------------------------------------------------------- -// fixPhaseForward -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints later than the specified time -//! so that the synthesize phases of those later Breakpoints matches -//! the stored phase, as long as the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. Breakpoints later than -//! tend are unmodified. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is simply left unmodified, -//! and future phases wil be recomputed from that one. -//! -//! \param p The Partial whose phases should be fixed. -//! \param tbeg The phases and frequencies of Breakpoints later than the -//! one nearest this time will be modified. -//! \param tend The phases and frequencies of Breakpoints earlier than the -//! one nearest this time will be modified. Should be greater -//! than tbeg, or else they will be swapped. -// -void fixPhaseForward( Partial & p, double tbeg, double tend ); - -// --------------------------------------------------------------------------- -// fixPhaseForward (range) -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints later than the specified time -//! so that the synthesize phases of those later Breakpoints matches -//! the stored phase, as long as the synthesized phase at the specified -//! time matches the stored (not recomputed) phase. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is simply left unmodified, -//! and future phases wil be recomputed from that one. -//! -//! \param b The beginning of a range of Partials whose phases -//! should be fixed. -//! \param e The end of a range of Partials whose phases -//! should be fixed. -//! \param tbeg The phases and frequencies of Breakpoints later than the -//! one nearest this time will be modified. -//! \param tend The phases and frequencies of Breakpoints earlier than the -//! one nearest this time will be modified. Should be greater -//! than tbeg, or else they will be swapped. -// -template < class Iter > -void fixPhaseForward( Iter b, Iter e, double tbeg, double tend ) -{ - while ( b != e ) - { - fixPhaseForward( *b, tbeg, tend ); - ++b; - } -} - - -// --------------------------------------------------------------------------- -// fixPhaseAt -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints in a Partial -//! so that the synthesized phases match the stored phases, -//! and the synthesized phase at (nearest) the specified -//! time matches the stored (not recomputed) phase. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the Partial -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the Partial. Forward phase fixing is only applied -//! to non-null (nonzero-amplitude) Breakpoints. If a null is encountered, -//! its phase is simply left unmodified, and future phases wil be -//! recomputed from that one. -//! -//! \param p The Partial whose phases should be fixed. -//! \param t The time at which phases should be made correct. -// -void fixPhaseAt( Partial & p, double t ); - -// --------------------------------------------------------------------------- -// fixPhaseAt (range) -// --------------------------------------------------------------------------- -//! Recompute phases of all Breakpoints in a Partial -//! so that the synthesize phases match the stored phases, -//! and the synthesized phase at (nearest) the specified -//! time matches the stored (not recomputed) phase. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the Partial -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the Partial. Forward phase fixing is only applied -//! to non-null (nonzero-amplitude) Breakpoints. If a null is encountered, -//! its phase is simply left unmodified, and future phases wil be -//! recomputed from that one. -//! -//! \param b The beginning of a range of Partials whose phases -//! should be fixed. -//! \param e The end of a range of Partials whose phases -//! should be fixed. -//! \param t The time at which phases should be made correct. -// -template < class Iter > -void fixPhaseAt( Iter b, Iter e, double t ) -{ - while ( b != e ) - { - fixPhaseAt( *b, t ); - ++b; - } -} - -// --------------------------------------------------------------------------- -// fixPhaseBetween -// --------------------------------------------------------------------------- -//! Fix the phase travel between two times by adjusting the -//! frequency and phase of Breakpoints between those two times. -//! -//! This algorithm assumes that there is nothing interesting about the -//! phases of the intervening Breakpoints, and modifies their frequencies -//! as little as possible to achieve the correct amount of phase travel -//! such that the frequencies and phases at the specified times -//! match the stored values. The phases of all the Breakpoints between -//! the specified times are recomputed. -//! -//! THIS DOES NOT YET TREAT NULL BREAKPOINTS DIFFERENTLY FROM OTHERS. -//! -//! \pre Thre must be at least one Breakpoint in the -//! Partial between the specified times t1 and t2. -//! If this condition is not met, the Partial is -//! unmodified. -//! \post The phases and frequencies of the Breakpoints in the -//! range have been recomputed such that an oscillator -//! initialized to the parameters of the first Breakpoint -//! will arrive at the parameters of the last Breakpoint, -//! and all the intervening Breakpoints will be matched. -//! \param p The partial whose phases and frequencies will be recomputed. -//! The Breakpoint at this position is unaltered. -//! \param t1 The time before which Partial frequencies and phases will -//! not be modified. -//! \param t2 The time after which Partial frequencies and phases will -//! not be modified. Should be greater than t1, or else they -//! will be swapped. -// -void fixPhaseBetween( Partial & p, double t1, double t2 ); - -// --------------------------------------------------------------------------- -// fixPhaseBetween (range) -// --------------------------------------------------------------------------- -//! Fix the phase travel between two times by adjusting the -//! frequency and phase of Breakpoints between those two times. -//! -//! This algorithm assumes that there is nothing interesting about the -//! phases of the intervening Breakpoints, and modifies their frequencies -//! as little as possible to achieve the correct amount of phase travel -//! such that the frequencies and phases at the specified times -//! match the stored values. The phases of all the Breakpoints between -//! the specified times are recomputed. -//! -//! THIS DOES NOT YET TREAT NULL BREAKPOINTS DIFFERENTLY FROM OTHERS. -//! -//! \pre Thre must be at least one Breakpoint in each -//! Partial between the specified times t1 and t2. -//! If this condition is not met, the Partial is -//! unmodified. -//! \post The phases and frequencies of the Breakpoints in the -//! range have been recomputed such that an oscillator -//! initialized to the parameters of the first Breakpoint -//! will arrive at the parameters of the last Breakpoint, -//! and all the intervening Breakpoints will be matched. -//! \param b The beginning of a range of Partials whose phases -//! should be fixed. -//! \param e The end of a range of Partials whose phases -//! should be fixed. -//! \param t1 The time before which Partial frequencies and phases will -//! not be modified. -//! \param t2 The time after which Partial frequencies and phases will -//! not be modified. Should be greater than t1, or else they -//! will be swapped. -// -template < class Iter > -void fixPhaseBetween( Iter b, Iter e, double t1, double t2 ) -{ - while ( b != e ) - { - fixPhaseBetween( *b, t1, t2 ); - ++b; - } -} - - - -// -- predicates -- - -// --------------------------------------------------------------------------- -// isDurationLess -// -//! Predicate functor returning true if the duration of its -//! Partial argument is less than the specified duration in -//! seconds, and false otherwise. -// -class isDurationLess : public std::unary_function< const Partial, bool > -{ -public: - //! Initialize a new instance with the specified label. - isDurationLess( double x ) : mDurationSecs(x) {} - - //! Function call operator: evaluate a Partial. - bool operator()( const Partial & p ) const - { return p.duration() < mDurationSecs; } - - //! Function call operator: evaluate a Partial pointer. - bool operator()( const Partial * p ) const - { return p->duration() < mDurationSecs; } - -private: - double mDurationSecs; -}; - -// --------------------------------------------------------------------------- -// isLabelEqual -// -//! Predicate functor returning true if the label of its Partial argument is -//! equal to the specified 32-bit label, and false otherwise. -// -class isLabelEqual : public std::unary_function< const Partial, bool > -{ -public: - //! Initialize a new instance with the specified label. - isLabelEqual( int l ) : label(l) {} - - //! Function call operator: evaluate a Partial. - bool operator()( const Partial & p ) const - { return p.label() == label; } - - //! Function call operator: evaluate a Partial pointer. - bool operator()( const Partial * p ) const - { return p->label() == label; } - -private: - int label; -}; - -// --------------------------------------------------------------------------- -// isLabelGreater -// -//! Predicate functor returning true if the label of its Partial argument is -//! greater than the specified 32-bit label, and false otherwise. -// -class isLabelGreater : public std::unary_function< const Partial, bool > -{ -public: - //! Initialize a new instance with the specified label. - isLabelGreater( int l ) : label(l) {} - - //! Function call operator: evaluate a Partial. - bool operator()( const Partial & p ) const - { return p.label() > label; } - - //! Function call operator: evaluate a Partial pointer. - bool operator()( const Partial * p ) const - { return p->label() > label; } - -private: - int label; -}; - -// --------------------------------------------------------------------------- -// isLabelLess -// -//! Predicate functor returning true if the label of its Partial argument is -//! less than the specified 32-bit label, and false otherwise. -// -class isLabelLess : public std::unary_function< const Partial, bool > -{ -public: - //! Initialize a new instance with the specified label. - isLabelLess( int l ) : label(l) {} - - //! Function call operator: evaluate a Partial. - bool operator()( const Partial & p ) const - { return p.label() < label; } - - //! Function call operator: evaluate a Partial pointer. - bool operator()( const Partial * p ) const - { return p->label() < label; } - -private: - int label; -}; - -// --------------------------------------------------------------------------- -// isPeakLess -// -//! Predicate functor returning true if the peak amplitude achieved by its -//! Partial argument is less than the specified absolute amplitude, and -//! false otherwise. -// -class isPeakLess : public std::unary_function< const Partial, bool > -{ -public: - //! Initialize a new instance with the specified peak amplitude. - isPeakLess( double x ) : thresh(x) {} - - //! Function call operator: evaluate a Partial. - bool operator()( const Partial & p ) const - { return peakAmplitude( p ) < thresh; } - - //! Function call operator: evaluate a Partial pointer. - bool operator()( const Partial * p ) const - { return peakAmplitude( *p ) < thresh; } - -private: - double thresh; -}; - -// -- comparitors -- - -// --------------------------------------------------------------------------- -// compareLabelLess -// -//! Comparitor (binary) functor returning true if its first Partial -//! argument has a label whose 32-bit integer representation is less than -//! that of the second Partial argument's label, and false otherwise. -// -class compareLabelLess : - public std::binary_function< const Partial, const Partial, bool > -{ -public: - //! Compare two Partials, return true if its first Partial - //! argument has a label whose 32-bit integer representation is less than - //! that of the second Partial argument's label, and false otherwise. - bool operator()( const Partial & lhs, const Partial & rhs ) const - { return lhs.label() < rhs.label(); } - - //! Compare two Partials, return true if its first Partial - //! argument has a label whose 32-bit integer representation is less than - //! that of the second Partial argument's label, and false otherwise. - bool operator()( const Partial * lhs, const Partial * rhs ) const - { return lhs->label() < rhs->label(); } -}; - -// --------------------------------------------------------------------------- -// compareDurationLess -// -//! Comparitor (binary) functor returning true if its first Partial -//! argument has duration less than that of the second Partial -//! argument, and false otherwise. -// -class compareDurationLess : - public std::binary_function< const Partial, const Partial, bool > -{ -public: - //! Compare two Partials, return true if its first Partial - //! argument has duration less than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial & lhs, const Partial & rhs ) const - { return lhs.duration() < rhs.duration(); } - - //! Compare two Partials, return true if its first Partial - //! argument has duration less than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial * lhs, const Partial * rhs ) const - { return lhs->duration() < rhs->duration(); } -}; - -// --------------------------------------------------------------------------- -// compareDurationGreater -// -//! Comparitor (binary) functor returning true if its first Partial -//! argument has duration greater than that of the second Partial -//! argument, and false otherwise. -// -class compareDurationGreater : - public std::binary_function< const Partial, const Partial, bool > -{ -public: - //! Compare two Partials, return true if its first Partial - //! argument has duration greater than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial & lhs, const Partial & rhs ) const - { return lhs.duration() > rhs.duration(); } - - //! Compare two Partials, return true if its first Partial - //! argument has duration greater than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial * lhs, const Partial * rhs ) const - { return lhs->duration() > rhs->duration(); } -}; - -// --------------------------------------------------------------------------- -// compareStartTimeLess -// -//! Comparitor (binary) functor returning true if its first Partial -//! argument has start time earlier than that of the second Partial -//! argument, and false otherwise. -// -class compareStartTimeLess : - public std::binary_function< const Partial, const Partial, bool > -{ -public: - //! Compare two Partials, return true if its first Partial - //! argument has start time earlier than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial & lhs, const Partial & rhs ) const - { return lhs.startTime() < rhs.startTime(); } - - //! Compare two Partials, return true if its first Partial - //! argument has start time earlier than that of the second Partial - //! argument, and false otherwise. - bool operator()( const Partial * lhs, const Partial * rhs ) const - { return lhs->startTime() < rhs->startTime(); } -}; - - - -} // end of namespace PartialUtils - -} // end of namespace Loris - -#endif /* ndef INCLUDE_PARTIALUTILS_H */ diff --git a/loris_library/Source/src/README b/loris_library/Source/src/README deleted file mode 100644 index 0a2ab2b..0000000 --- a/loris_library/Source/src/README +++ /dev/null @@ -1,4 +0,0 @@ -This directory contains the source code for the Loris C++ library. In -addition to the interface presented by the C++ classes, the Loris -library presents a simplified, C-linkable procedural interface through -the functions descried in loris.h diff --git a/loris_library/Source/src/ReassignedSpectrum.cpp b/loris_library/Source/src/ReassignedSpectrum.cpp deleted file mode 100644 index 0292905..0000000 --- a/loris_library/Source/src/ReassignedSpectrum.cpp +++ /dev/null @@ -1,746 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * ReassignedSpectrum.C - * - * Implementation of class Loris::ReassignedSpectrum. - * - * Kelly Fitz, 9 Dec 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "ReassignedSpectrum.h" -#include "Notifier.h" -#include "LorisExceptions.h" -#include // for std::transform(), others -#include // for bind1st, multiplies, etc. -#include // for std::abs() -#include // for std::accumulate() - -#include // for M_PI (except when its not there), fmod, fabs -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -// The old quadratic interpolation code is still around, in case -// we ever want to use it for comparison, Lemur used to use that. -#if defined(Like_Lemur) -#define USE_PARABOLIC_INTERPOLATION -#endif - -// define this symbol to compute the mixed phase derivative -#define COMPUTE_MIXED_PHASE_DERIVATIVE 1 - -// there's a lot of std in here, -// import the whole namespace, as ugly as that is. -using namespace std; - -// begin namespace -namespace Loris { - -static unsigned long nextPO2( unsigned long N ) -{ - return (unsigned long)ceil( log( double(N) ) / log( 2. ) ); -} - -// --------------------------------------------------------------------------- -// ReassignedSpectrum constructor -// --------------------------------------------------------------------------- -//! Construct a new instance using the specified short-time window. -//! Transform lengths are the smallest power of two greater than twice the -//! window length. -// -ReassignedSpectrum::ReassignedSpectrum( const std::vector< double > & window ) : - mMagnitudeTransform( 1 << ( 1 + nextPO2( window.size() ) ) ), - mCorrectionTransform( 1 << ( 1 + nextPO2( window.size() ) ) ) -{ - // Build and store the window functions. - buildReassignmentWindows( window ); - - debugger << "ReassignedSpectrum: length is " << mMagnitudeTransform.size() << endl; -} - -// --------------------------------------------------------------------------- -// ReassignedSpectrum constructor -// --------------------------------------------------------------------------- -//! Construct a new instance using the specified short-time window and -//! its time derivative. -//! Transform lengths are the smallest power of two greater than twice the -//! window length. -ReassignedSpectrum::ReassignedSpectrum( const std::vector< double > & window, - const std::vector< double > & windowDerivative ) : - mMagnitudeTransform( 1 << ( 1 + nextPO2( window.size() ) ) ), - mCorrectionTransform( 1 << ( 1 + nextPO2( window.size() ) ) ) -{ - // Build and store the window functions. - buildReassignmentWindows( window, windowDerivative ); - - debugger << "ReassignedSpectrum: length is " << mMagnitudeTransform.size() << endl; -} - - -// --------------------------------------------------------------------------- -// transform -// --------------------------------------------------------------------------- -//! Compute the reassigned Fourier transform of the samples on the half open -//! range [sampsBegin, sampsEnd), aligning sampCenter with the center of -//! the analysis window. -//! -//! \param sampsBegin pointer representing the beginning of -//! the (half-open) range of samples to transform -//! \param sampCenter the sample in the range that is to be -//! aligned with the center of the analysis window -//! \param sampsEnd pointer representing the end of -//! the (half-open) range of samples to transform -//! -//! \pre sampsBegin must not be past sampCenter -//! \pre sampsEnd must be past sampCenter -//! \post the transform buffers store the reassigned -//! short-time transform data for the specified -//! samples -// -void -ReassignedSpectrum::transform( const double * sampsBegin, - const double * sampCenter, - const double * sampsEnd ) -{ - if ( sampCenter < sampsBegin || sampCenter >= sampsEnd ) - { - Throw( InvalidArgument, "Invalid sample range boundaries." ); - } - - const long firstHalfWinLength = window().size() / 2; - const long secondHalfWinLength = (window().size() - 1) / 2; - - // ensure that samples outside the window are not used: - sampsBegin = std::max( sampsBegin, sampCenter - firstHalfWinLength ); - sampsEnd = std::min( sampsEnd, sampCenter + secondHalfWinLength + 1 ); - - // we will skip the beginning of the window - // only if pos is too close to the start of - // the buffer: - long winBeginOffset = 0; - if ( sampCenter - sampsBegin < (window().size() / 2) ) - { - winBeginOffset = (window().size() / 2) - ( sampCenter - sampsBegin ); - } - - // to get phase right, we will rotate the Fourier transform - // input by pos - sampsBegin samples: - long rotateBy = sampCenter - sampsBegin; - - // window and rotate input and compute normal transform: - // window the samples into the FT buffer: - FourierTransform::iterator it = - std::transform( sampsBegin, sampsEnd, mCplxWin_W_Wtd.begin() + winBeginOffset, - mMagnitudeTransform.begin(), std::multiplies< std::complex< double > >() ); - // fill the rest with zeros: - std::fill( it, mMagnitudeTransform.end(), 0. ); - // rotate to align phase: - std::rotate( mMagnitudeTransform.begin(), mMagnitudeTransform.begin() + rotateBy, mMagnitudeTransform.end() ); - - // compute transform: - mMagnitudeTransform.transform(); - - // compute the dual reassignment transform: - // window the samples into the reassignment FT buffer, - // using the complex-valued reassignment window: - it = std::transform( sampsBegin, sampsEnd, mCplxWin_Wd_Wt.begin() + winBeginOffset, - mCorrectionTransform.begin(), std::multiplies< std::complex >() ); - // fill the rest with zeros: - std::fill( it, mCorrectionTransform.end(), 0. ); - // rotate to align phase: - std::rotate( mCorrectionTransform.begin(), mCorrectionTransform.begin() + rotateBy, mCorrectionTransform.end() ); - // compute the transform: - mCorrectionTransform.transform(); -} - -// --------------------------------------------------------------------------- -// size -// --------------------------------------------------------------------------- -//! Return the length of the Fourier transforms. -// -ReassignedSpectrum::size_type -ReassignedSpectrum::size( void ) const -{ - return mMagnitudeTransform.size(); -} - -// --------------------------------------------------------------------------- -// window -// --------------------------------------------------------------------------- -//! Return read access to the short-time window samples. -//! (Peers may need to know about the analysis window -//! or about the scale factors in introduces.) -// -const std::vector< double > & -ReassignedSpectrum::window( void ) const -{ - return mWindow; -} - -// --------------------------------------------------------------------------- -// circEvenPartAt - helper -// --------------------------------------------------------------------------- -// Extract the circular even part from Fourier transform data. -// Used for computing two real transforms using a single complex transform. -// -template< class TransformData > -static std::complex -circEvenPartAt( const TransformData & td, long idx ) -{ - const long N = td.size(); - while( idx < 0 ) - { - idx += N; - } - while( idx >= N ) - { - idx -= N; - } - - long flip_idx; - if ( idx != 0 ) - { - flip_idx = N - idx; - } - else - { - flip_idx = idx; - } - - return 0.5*( td[idx] + std::conj( td[flip_idx] ) ); -} - -// --------------------------------------------------------------------------- -// circOddPartAt - helper -// --------------------------------------------------------------------------- -// Extract the circular odd part divided by j from Fourier transform data. -// Used for computing two real transforms using a single complex transform. -// -template< class TransformData > -static std::complex -circOddPartAt( const TransformData & td, long idx ) -{ - const long N = td.size(); - while( idx < 0 ) - { - idx += N; - } - while( idx >= N ) - { - idx -= N; - } - - long flip_idx; - if ( idx != 0 ) - { - flip_idx = N - idx; - } - else - { - flip_idx = idx; - } - - /* - const std::complex minus_j(0,-1); - std::complex tra_part = minus_j * 0.5 * - ( td[idx] - std::conj( td[flip_idx] ) ); - */ - // can compute this without complex multiplies: - std::complex tmp = td[idx] - std::conj( td[flip_idx] ); - return std::complex( 0.5*tmp.imag(), -0.5*tmp.real() ); -} - -// --------------------------------------------------------------------------- -// frequencyCorrection -// --------------------------------------------------------------------------- -//! Compute the frequency correction at the specified frequency sample -//! using the method of Auger and Flandrin to evaluate the partial -//! derivative of spectrum phase w.r.t. time. -//! -//! Correction is computed in fractional frequency samples, because -//! that's the kind of frequency domain ramp we used on our window. -//! sample is the frequency sample index, the nominal component -//! frequency in samples. -// -// Parabolic interpolation can be tried too (see reassignedFrequency()) -// but it appears to give slightly worse results, for example, with -// a square wave. -// -double -ReassignedSpectrum::frequencyCorrection( long idx ) const -{ - std::complex X_h = circEvenPartAt( mMagnitudeTransform, idx ); - std::complex X_Dh = circEvenPartAt( mCorrectionTransform, idx ); - - double num = X_h.real() * X_Dh.imag() - - X_h.imag() * X_Dh.real(); - - double magSquared = std::norm( X_h ); - - // need to scale by the oversampling factor - double oversampling = (double)mCorrectionTransform.size() / mCplxWin_W_Wtd.size(); - return - oversampling * num / magSquared; -} - -// --------------------------------------------------------------------------- -// timeCorrection -// --------------------------------------------------------------------------- -//! Compute the time correction at the specified frequency sample -//! using the method of Auger and Flandrin to evaluate the partial -//! derivative of spectrum phase w.r.t. frequency. -//! -//! Correction is computed in fractional samples, because -//! that's the kind of ramp we used on our window. -// -double -ReassignedSpectrum::timeCorrection( long idx ) const -{ - std::complex X_h = circEvenPartAt( mMagnitudeTransform, idx ); - std::complex X_Th = circOddPartAt( mCorrectionTransform, idx ); - - double num = X_h.real() * X_Th.real() + - X_h.imag() * X_Th.imag(); - double magSquared = norm( X_h ); - - // No need to scale by the oversampling factor. - // No, seems to sound bad, why? - // (try alienthreat) - // double oversampling = (double)mCorrectionTransform.size() / mCplxWin_W_Wtd.size(); - return num / magSquared; -} - -// --------------------------------------------------------------------------- -// reassignedFrequency -// --------------------------------------------------------------------------- -//! Return the reassigned frequency in fractional frequency -//! samples computed at the specified transform index. -//! -//! \param idx the frequency sample at which to evaluate the -//! transform -// -double -ReassignedSpectrum::reassignedFrequency( long idx ) const -{ -#if ! defined(USE_PARABOLIC_INTERPOLATION) - - return double(idx) + frequencyCorrection( idx ); - -#else // defined(USE_PARABOLIC_INTERPOLATION) - - double dbLeft = 20. * log10( abs( circEvenPartAt( mMagnitudeTransform, idx-1 ) ) ); - double dbCandidate = 20. * log10( abs( circEvenPartAt( mMagnitudeTransform, idx ) ) ); - double dbRight = 20. * log10( abs( circEvenPartAt( mMagnitudeTransform, idx+1 ) ) ); - - double peakXOffset = 0.5 * (dbLeft - dbRight) / - (dbLeft - 2.0 * dbCandidate + dbRight); - - return idx + peakXOffset; - -#endif // defined USE_PARABOLIC_INTERPOLATION -} - -// --------------------------------------------------------------------------- -// reassignedTime -// --------------------------------------------------------------------------- -//! Return the reassigned time in fractional samples -//! computed at the specified transform index. -//! -//! \param idx the frequency sample at which to evaluate the -//! transform -// -double -ReassignedSpectrum::reassignedTime( long idx ) const -{ - return timeCorrection( idx ); -} - -// --------------------------------------------------------------------------- -// reassignedMagnitude -// --------------------------------------------------------------------------- -//! Return the spectrum magnitude (absolute) -//! computed at the specified transform index. -//! -//! \param idx the frequency sample at which to evaluate the -//! transform -// -double -ReassignedSpectrum::reassignedMagnitude( long idx ) const -{ -#if ! defined(USE_PARABOLIC_INTERPOLATION) - - // compute the nominal spectral amplitude by scaling - // the peak spectral sample: - return abs( circEvenPartAt( mMagnitudeTransform, idx ) ); - -#else // defined(USE_PARABOLIC_INTERPOLATION) - - // keep this parabolic interpolation computation around - // only for sake of comparison, it is unlikely to yield - // good results with bandwidth association: - double dbLeft = 20. * log10( abs( circEvenPartAt( mMagnitudeTransform, idx-1 ) ) ); - double dbCandidate = 20. * log10( abs( circEvenPartAt( mMagnitudeTransform, idx ) ) ); - double dbRight = 20. * log10( abs( circEvenPartAt( mMagnitudeTransform, idx+1 ) ) ); - - double peakXOffset = 0.5 * (dbLeft - dbRight) / - (dbLeft - 2.0 * dbCandidate + dbRight); - double dbmag = dbCandidate - 0.25 * (dbLeft - dbRight) * peakXOffset; - double x = pow( 10., 0.05 * dbmag ); - - return x; - -#endif // defined USE_PARABOLIC_INTERPOLATION -} - -// --------------------------------------------------------------------------- -// reassignedPhase -// --------------------------------------------------------------------------- -//! Return the phase in radians computed at the specified transform index. -//! The reassigned phase is shifted to account for the time -//! correction according to the corrected frequency. -//! -//! \param idx the frequency sample at which to evaluate the -//! transform -// -double -ReassignedSpectrum::reassignedPhase( long idx ) const -{ - double phase = arg( circEvenPartAt( mMagnitudeTransform, idx ) ); - - const double offsetTime = timeCorrection( idx ); - const double offsetFreq = frequencyCorrection( idx ); - - // adjust phase according to the frequency correction: - // first compute H(1): - // - // this seems like it would be a good idea, but in practice, - // it screws the phases up badly. - // Am I just correcting in the wrong direction? No, its - // something else. - // - // Seems like I had the slope way too big. Changed to compute - // the slope from H(1) of a rotated window, and now the slope - // is so small that it seems like there will never be any phase - // correction. - // - // Phase ought to be linear anyway, so I should just be - // able to use dumb old linear interpolation. - // offsetFreq is in fractional frequency samples - if ( offsetFreq > 0 ) - { - double nextphase = arg( circEvenPartAt( mMagnitudeTransform, idx+1 ) ); - double slope = nextphase - phase; - phase += offsetFreq * slope; - } - else - { - double prevphase = arg( circEvenPartAt( mMagnitudeTransform, idx-1 ) ); - double slope = phase - prevphase; - phase += offsetFreq * slope; - } - - - // adjust phase according to the time correction: - const double fracFreqSample = idx + offsetFreq; - phase += offsetTime * fracFreqSample * 2. * Pi / mMagnitudeTransform.size(); - - // NOTICE - // This could be pretty much anything -- a sample reassigned by a - // millisecond at 1000 Hz in a 1024 FFT at 44k sample rate is - // adjusted by 2Pi. - // - // What if the frequency estimate is bad? Corrupts the phase estimate too! - - return fmod( phase, 2. * Pi ); -} - -// --------------------------------------------------------------------------- -// convergence -// --------------------------------------------------------------------------- -//! Compute and return the convergence indicator, computed from the -//! mixed partial derivative of spectral phase, optionally used in -//! BW enhanced analysis as a convergence indicator. The convergence -//! value is on the range [0,1], 0 for a sinusoid, and 1 for an impulse. -//! -//! \param idx the frequency sample at which to evaluate the -//! transform -// -double -ReassignedSpectrum::convergence( long idx ) const -{ -#if defined(COMPUTE_MIXED_PHASE_DERIVATIVE) - - std::complex X_h = circEvenPartAt( mMagnitudeTransform, idx ); - std::complex X_Th = circOddPartAt( mCorrectionTransform, idx ); - std::complex X_Dh = circEvenPartAt( mCorrectionTransform, idx ); - std::complex X_TDh = circOddPartAt( mMagnitudeTransform, idx ); - - double term1 = (X_TDh * conj(X_h)).real() / norm( X_h ); - double term2 = ((X_Th * X_Dh) / (X_h * X_h)).real(); - - double scaleBy = 2. * Pi / mCplxWin_W_Wtd.size(); - - double bw = fabs( 1.0 + (scaleBy * (term1 - term2)) ); - bw = min( 1.0, bw ); - -#else - double bw = 0.; -#endif - - return bw; -} - -// --------------------------------------------------------------------------- -// subscript operator (deprecated) -// --------------------------------------------------------------------------- -// Included to support old code. -// The signature has changed, can no longer return a reference, -// but since the reference returned was const, this version should -// keep most old code working, if not all. -// -std::complex< double > -ReassignedSpectrum::operator[]( unsigned long idx ) const -{ - return circEvenPartAt( mMagnitudeTransform, idx ); -} - -// --------------------------------------------------------------------------- -// make_complex -// --------------------------------------------------------------------------- -// Function object for building complex numbers. -// -template -struct make_complex - : binary_function< T, T, std::complex > -{ - std::complex operator()(const T& re, const T& im) const - { - return std::complex( re, im ); - } -}; - -// --------------------------------------------------------------------------- -// applyFreqRamp -// --------------------------------------------------------------------------- -// Adapted from the FrequencyReassignment constructor in Lemur 5. -// -// This function computes an estimate of the time derivative of the -// specified window function, scaled by N/2pi, appropriate for computing -// frequency reassignment. -// -static inline void applyFreqRamp( vector< double > & w ) -{ - // we're going to do the frequency-domain ramp - // by Fourier transforming the window, ramping, - // then transforming again. - // Use a transform exactly as long as the window. - // load, w/out rotation, and transform. - FourierTransform temp( w.size() ); - FourierTransform::iterator it = std::copy( w.begin(), w.end(), temp.begin() ); - std::fill( it, temp.end(), 0. ); - temp.transform(); - - // extract complex transform and multiply by - // a frequency (sample) ramp: - // (the frequency ramp goes from 0 to N/2 - // over the first half, then -N/2 to 0 over - // the second (aliased) half of the transform, - // and has to be scaled by the ratio of the - // transform lengths, so that k spans the length - // of the padded transforms, N) - for ( int k = 0 ; k < temp.size(); ++k ) - { - double x = (double)k; // to get type promotion right - if ( k < temp.size() / 2 ) - { - temp[ k ] *= x; - } - else - { - temp[ k ] *= ( x - temp.size() ); - } - } - - // invert the transform: - temp.transform(); - - // the DFT of a DFT gives the scaled and INDEX REVERSED - // sequence. See p. 539 of O and S. - // DFT( X[n] ) -- DFT --> Nx[ -k mod N ] - // - // seems that I want the imaginary part of the index-reversed - // transform scaled by the size of the transform: - std::reverse( temp.begin() + 1, temp.end() ); - for ( int i = 0; i < w.size(); ++i ) - { - w[i] = - imag( temp[i] ) / temp.size(); - } -} - -// --------------------------------------------------------------------------- -// applyTimeRamp -// --------------------------------------------------------------------------- -// Make a copy of mWindow scaled by a ramp from -N/2 to N/2 for computing -// time corrections in samples. -// -static inline void applyTimeRamp( vector< double > & w ) -{ - // the very center of the window should be scaled by 0., - // need a fractional value for even-length windows, a - // whole number for odd-length windows: - double offset = 0.5 * ( w.size() - 1 ); - for ( int k = 0 ; k < w.size(); ++k ) - { - w[ k ] *= ( k - offset ); - } -} - -// --------------------------------------------------------------------------- -// buildReassignmentWindows (private) -// --------------------------------------------------------------------------- -// Build a pair of complex-valued windows, one having the frequency-ramp -// (time-derivative) window in the real part and the time-ramp window in the -// imagnary part, and the other having the unmodified window in the real part -// and, if computing mixed deriviatives, the time-ramp time-derivative window -// in the imaginary part. -// -// Input is the unmodified window function. -// -void -ReassignedSpectrum::buildReassignmentWindows( const std::vector< double > & window ) -{ - mWindow.resize( window.size(), 0. ); - - // Scale the window so that the reported magnitudes - // are correct. - double winsum = std::accumulate( window.begin(), window.end(), 0. ); - std::transform( window.begin(), window.end(), mWindow.begin(), - std::bind1st( std::multiplies(), 2/winsum ) ); - - - // Construct the ramped windows from the scaled window. - std::vector< double > tramp = mWindow; - applyTimeRamp( tramp ); - - std::vector< double > framp = mWindow; - applyFreqRamp( framp ); - - std::vector< double > tframp( mWindow.size(), 0. ); - -#if defined(COMPUTE_MIXED_PHASE_DERIVATIVE) - - // Do this only if we are computing the mixed - // partial derivative of phase, otherwise, leave - // that vector empty. - tframp = framp; - applyTimeRamp( tframp ); - -#endif - - // Copy the windows into real and imaginary parts of - // complex window vectors. - mCplxWin_W_Wtd.resize( mWindow.size(), 0. ); - mCplxWin_Wd_Wt.resize( mWindow.size(), 0. ); - - std::transform( framp.begin(), framp.end(), tramp.begin(), - mCplxWin_Wd_Wt.begin(), make_complex< double >() ); - - std::transform( mWindow.begin(), mWindow.end(), tframp.begin(), - mCplxWin_W_Wtd.begin(), make_complex< double >() ); -} - -// --------------------------------------------------------------------------- -// buildReassignmentWindows -// --------------------------------------------------------------------------- -// Build a pair of complex-valued windows, one having the frequency-ramp -// (time-derivative) window in the real part and the time-ramp window in the -// imagnary part, and the other having the unmodified window in the real part -// and, if computing mixed deriviatives, the time-ramp time-derivative window -// in the imaginary part. -// -// Input is the unmodified window function and its time derivative, so the -// DFT kludge is unnecessary. -// - -void -ReassignedSpectrum::buildReassignmentWindows( const std::vector< double > & window, - const std::vector< double > & windowDerivative ) -{ - - mWindow.resize( window.size(), 0. ); - - // Scale the windows so that the reported magnitudes - // are correct. - double winsum = std::accumulate( window.begin(), window.end(), 0. ); - std::transform( window.begin(), window.end(), mWindow.begin(), - std::bind1st( std::multiplies(), 2/winsum ) ); - - - // The fancy frequency reassignment window needs to scale the - // time derivative window by N (its length) / 2pi, in addition - // to scaling by 2/winsum to match the amplitude scaling above. - const double fancyScale = windowDerivative.size() / ( winsum * Pi ); - std::vector< double > framp( windowDerivative.size(), 0 ); - std::transform( windowDerivative.begin(), windowDerivative.end(), framp.begin(), - std::bind1st( std::multiplies(), fancyScale ) ); - - - // Construct the ramped windows from the scaled window. - std::vector< double > tramp = mWindow; - applyTimeRamp( tramp ); - - std::vector< double > tframp( mWindow.size(), 0. ); - -#if defined(COMPUTE_MIXED_PHASE_DERIVATIVE) - - // Do this only if we are computing the mixed - // partial derivative of phase, otherwise, leave - // that vector empty. - tframp = framp; - applyTimeRamp( tframp ); - -#endif - - // Copy the windows into real and imaginary parts of - // complex window vectors. - mCplxWin_W_Wtd.resize( mWindow.size(), 0. ); - mCplxWin_Wd_Wt.resize( mWindow.size(), 0. ); - - std::transform( framp.begin(), framp.end(), tramp.begin(), - mCplxWin_Wd_Wt.begin(), make_complex< double >() ); - - std::transform( mWindow.begin(), mWindow.end(), tframp.begin(), - mCplxWin_W_Wtd.begin(), make_complex< double >() ); -} - - -} // end of namespace Loris diff --git a/loris_library/Source/src/ReassignedSpectrum.h b/loris_library/Source/src/ReassignedSpectrum.h deleted file mode 100644 index cd8ae69..0000000 --- a/loris_library/Source/src/ReassignedSpectrum.h +++ /dev/null @@ -1,229 +0,0 @@ -#ifndef INCLUDE_REASSIGNEDSPECTRUM_H -#define INCLUDE_REASSIGNEDSPECTRUM_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * ReassignedSpectrum.h - * - * Definition of class Loris::ReassignedSpectrum. - * - * Kelly Fitz, 7 Dec 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "FourierTransform.h" -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class ReassignedSpectrum -// -//! Computes a reassigned short-time Fourier spectrum using the transform -//! method of Auger and Flandrin. -// -class ReassignedSpectrum -{ -// -- public interface -- -public: - //! An unsigned integral type large enough - //! to represent the length of any transform. - typedef FourierTransform::size_type size_type; - -// --- lifecycle --- - - //! Construct a new instance using the specified short-time window. - //! Transform lengths are the smallest power of two greater than twice the - //! window length. - ReassignedSpectrum( const std::vector< double > & window ); - - //! Construct a new instance using the specified short-time window and - //! its time derivative. - //! Transform lengths are the smallest power of two greater than twice the - //! window length. - ReassignedSpectrum( const std::vector< double > & window, - const std::vector< double > & windowDerivative ); - - // compiler-generated copy, assign, and destroy are sufficient - -// --- operations --- - - //! Compute the reassigned Fourier transform of the samples on the half open - //! range [sampsBegin, sampsEnd), aligning sampCenter with the center of - //! the analysis window. - //! - //! \param sampsBegin pointer representing the beginning of - //! the (half-open) range of samples to transform - //! \param sampCenter the sample in the range that is to be - //! aligned with the center of the analysis window - //! \param sampsEnd pointer representing the end of - //! the (half-open) range of samples to transform - //! - //! \pre sampsBegin must not be past sampCenter - //! \pre sampsEnd must be past sampCenter - //! \post the transform buffers store the reassigned - //! short-time transform data for the specified - //! samples - void transform( const double * sampsBegin, const double * pos, const double * sampsEnd ); - -// --- inquiry --- - - //! Return the length of the Fourier transforms. - size_type size( void ) const; - - //! Return read access to the short-time window samples. - //! (Peers may need to know about the analysis window - //! or about the scale factors in introduces.) - const std::vector< double > & window( void ) const; - - -// --- reassigned transform access --- - - //! Compute and return the convergence indicator, computed from the - //! mixed partial derivative of spectral phase, optionally used in - //! BW enhanced analysis as a convergence indicator. The convergence - //! value is on the range [0,1], 0 for a sinusoid, and 1 for an impulse. - //! - //! \param idx the frequency sample at which to evaluate the - //! transform - double convergence( long idx ) const; - - //! Return the reassigned frequency in fractional frequency - //! samples computed at the specified transform index. - //! - //! \param idx the frequency sample at which to evaluate the - //! transform - double reassignedFrequency( long idx ) const; - - //! Return the spectrum magnitude (absolute) - //! computed at the specified transform index. - //! - //! \param idx the frequency sample at which to evaluate the - //! transform - double reassignedMagnitude( long idx ) const; - - //! Return the phase in radians computed at the specified transform index. - //! The reassigned phase is shifted to account for the time - //! correction according to the corrected frequency. - //! - //! - //! \param idx the frequency sample at which to evaluate the - //! transform - double reassignedPhase( long idx ) const; - - //! Return the reassigned time in fractional samples - //! computed at the specified transform index. - //! - //! \param idx the frequency sample at which to evaluate the - //! transform - double reassignedTime( long idx ) const; - -// --- reassignment operations --- - - //! Compute the frequency correction at the specified frequency sample - //! using the method of Auger and Flandrin to evaluate the partial - //! derivative of spectrum phase w.r.t. time. - //! - //! Correction is computed in fractional frequency samples, because - //! that's the kind of frequency domain ramp we used on our window. - //! sample is the frequency sample index, the nominal component - //! frequency in samples. - double frequencyCorrection( long sample ) const; - - //! Compute the time correction at the specified frequency sample - //! using the method of Auger and Flandrin to evaluate the partial - //! derivative of spectrum phase w.r.t. frequency. - //! - //! Correction is computed in fractional samples, because - //! that's the kind of ramp we used on our window. - double timeCorrection( long sample ) const; - -// --- legacy support --- - - // These members are deprecated, and included only - // to support old code. New code should use the - // corresponding documented members. - // All of these members are deprecated. - - double reassignedPhase( long idx, double, double ) const - { return reassignedPhase( idx ); } - double reassignedMagnitude( double, long intBinNumber ) const - { return reassignedMagnitude( intBinNumber ); } - - // subscript operator - // The signature has changed, can no longer return a reference, - // but since the reference returned was const, this version should - // keep most old code working, if not all. - std::complex< double > operator[]( unsigned long idx ) const; - -private: - -// -- window building helpers -- - - // Build a pair of complex-valued windows, one having the frequency-ramp - // (time-derivative) window in the real part and the time-ramp window in the - // imagnary part, and the other having the unmodified window in the real part - // and, if computing mixed deriviatives, the time-ramp time-derivative window - // in the imaginary part. - // - // Input is the unmodified window function. - void buildReassignmentWindows( const std::vector< double > & window ); - - // Build a pair of complex-valued windows, one having the frequency-ramp - // (time-derivative) window in the real part and the time-ramp window in the - // imagnary part, and the other having the unmodified window in the real part - // and, if computing mixed deriviatives, the time-ramp time-derivative window - // in the imaginary part. - // - // Input is the unmodified window function and its time derivative, so the - // DFT kludge is unnecessary. - void buildReassignmentWindows( const std::vector< double > & window, - const std::vector< double > & windowDerivative ); - -// -- instance variables -- - - //! the FourierTransform for computing magnitude and phase - FourierTransform mMagnitudeTransform; - - //! the FourierTransform for computing time and frequency corrections - FourierTransform mCorrectionTransform; - - //! the original short-time analysis window samples - std::vector< double > mWindow; // W(n) - - //! the complex window used to compute the - //! magnitude/phase transform - std::vector< std::complex< double > > mCplxWin_W_Wtd; // real W(n), imag nW'(n) - - //! the complex window used to compute the - //! time/frequency correction transform - std::vector< std::complex< double > > mCplxWin_Wd_Wt; // real W'(n), imag nW(n) - -}; // end of class ReassignedSpectrum - -} // end of namespace Loris - -#endif /* ndef INCLUDE_REASSIGNEDSPECTRUM_H */ diff --git a/loris_library/Source/src/Resampler.cpp b/loris_library/Source/src/Resampler.cpp deleted file mode 100644 index be39674..0000000 --- a/loris_library/Source/src/Resampler.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Resampler.C - * - * Implementation of class Resampler, for converting reassigned Partial envelopes - * into more conventional additive synthesis envelopes, having data points - * at regular time intervals. The benefits of reassigned analysis are NOT - * lost in this process, since the elimination of unreliable data and the - * reduction of temporal smearing are reflected in the resampled data. - * - * Lippold, 7 Aug 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - * - * Phase correction added by Kelly 13 Dec 2005. - */ -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Resampler.h" -#include "Breakpoint.h" -#include "LinearEnvelope.h" -#include "LorisExceptions.h" -#include "Notifier.h" -#include "Partial.h" -#include "phasefix.h" - -#include - -// begin namespace -namespace Loris { - -// helper declarations: -static Partial::iterator insert_resampled_at( Partial & newp, const Partial & p, - double sampleTime, double insertTime ); - -/* -TODO - - remove empties (currently handled automatically in the Python module - - - remove insert_resampled_at - - - phase correct with timing? - - - fade time (for amplitude envelope sampling) - equal to interval? half? -*/ - - -// --------------------------------------------------------------------------- -// constructor - sampling interval -// --------------------------------------------------------------------------- -//! Initialize a Resampler having the specified uniform sampling -//! interval. Enable phase-correct resampling, in which frequencies -//! of resampled Partials are modified (using fixFrequency) such -//! that the resampled phases are achieved in synthesis. Phase- -//! correct resampling can be disabled using setPhaseCorrect. -//! -//! Resampled Partials will be composed of Breakpoints at every -//! integer multiple of the resampling interval. -//! -//! \sa setPhaseCorrect -//! \sa fixFrequency -//! -//! \param sampleInterval is the resampling interval in seconds, -//! Breakpoint data is computed at integer multiples of -//! sampleInterval seconds. -//! \throw InvalidArgument if sampleInterval is not positive. -// -Resampler::Resampler( double sampleInterval ) : - interval_( sampleInterval ), - phaseCorrect_( true ) -{ - if ( sampleInterval <= 0. ) - { - Throw( InvalidArgument, "Resampler sample interval must be positive." ); - } -} - -// --------------------------------------------------------------------------- -// setPhaseCorrect -// --------------------------------------------------------------------------- -//! Specify phase-corrected resampling, or not. If phase -//! correct, Partial frequencies are altered slightly -//! to match, as nearly as possible, the Breakpoint -//! phases after resampling. Phases are updated so that -//! the Partial frequencies and phases are consistent after -//! resampling. -//! -//! \param correctPhase is a boolean flag specifying that -//! (if true) frequency/phase correction should be -//! applied after resampling. -void Resampler::setPhaseCorrect( bool correctPhase ) -{ - phaseCorrect_ = correctPhase; -} - -// --------------------------------------------------------------------------- -// resample -// --------------------------------------------------------------------------- -//! Resample a Partial using this Resampler's stored quanitization interval. -//! If sparse resampling (the default) has be selected, Breakpoint times -//! are quantized to integer multiples of the resampling interval. -//! If dense resampling is selected, a Breakpoint will be provided at -//! every integer multiple of the resampling interval in the time span of -//! the Partial, starting and ending with the nearest multiples to the -//! ends of the Partial. Frequencies and phases are corrected to be in -//! agreement and to match as nearly as possible the resampled phases if -//! phase correct resampling is specified (the default). Resampling -//! is performed in-place. -//! -//! \param p is the Partial to resample -// -void -Resampler::resample( Partial & p ) const -{ - debugger << "resampling Partial labeled " << p.label() - << " having " << p.numBreakpoints() - << " Breakpoints" << endl; - - - // create the new Partial: - Partial newp; - newp.setLabel( p.label() ); - - // find time of first and last breakpoint for the resampled envelope: - double firstInsertTime = interval_ * int( 0.5 + p.startTime() / interval_ ); - double lastInsertTime = p.endTime() + ( 0.5 * interval_ ); - - // resample: - for ( double tins = firstInsertTime; tins <= lastInsertTime; tins += interval_ ) - { - // sample time is obtained from the timing envelope, if specified, - // otherwise same as the insert time: - double tsamp = tins; - insert_resampled_at( newp, p, tins, tins ); - } - - // store the new Partial: - p = newp; - - debugger << "resampled Partial has " << p.numBreakpoints() - << " Breakpoints" << endl; - - - if ( phaseCorrect_ ) - { - fixFrequency( p ); // use default maxFixPct - } -} - -// --------------------------------------------------------------------------- -// resample -// --------------------------------------------------------------------------- -//! Resample a Partial using this Resampler's stored quanitization interval. -//! If sparse resampling (the default) has be selected, Breakpoint times -//! are quantized to integer multiples of the resampling interval. -//! If dense resampling is selected, a Breakpoint will be provided at -//! every integer multiple of the resampling interval in the time span of -//! the Partial, starting and ending with the nearest multiples to the -//! ends of the Partial. Frequencies and phases are corrected to be in -//! agreement and to match as nearly as possible the resampled phases if -//! phase correct resampling is specified (the default). Resampling -//! is performed in-place. -//! -//! \param p is the Partial to resample -//! -//! \param timingEnv is the timing envelope, a map of Breakpoint -//! times in resampled Partials onto parameter sampling -//! instants in the original Partials. -//! -//! \throw InvalidArgument if timingEnv has any negative breakpoint -//! times or values. -// -void -Resampler::resample( Partial & p, const LinearEnvelope & timingEnv ) const -{ - debugger << "resampling Partial labeled " << p.label() - << " having " << p.numBreakpoints() - << " Breakpoints" << endl; - - - Assert( 0 != timingEnv.size() ); - - // create the new Partial: - Partial newp; - newp.setLabel( p.label() ); - - // find the extent of the timing envelope, if specified, otherwise - // the insert time range is the same as the sample time range: - double firstInsertTime = interval_ * int( 0.5 + timingEnv.begin()->first / interval_ ); - double lastInsertTime = (--timingEnv.end())->first + ( 0.5 * interval_ ); - - // resample: - for ( double insertTime = firstInsertTime; - insertTime <= lastInsertTime; - insertTime += interval_ ) - { - // sample time is obtained from the timing envelope, if specified, - // otherwise same as the insert time: - double sampleTime = timingEnv.valueAt( insertTime ); - - // make a resampled Breakpoint: - Breakpoint newbp = p.parametersAt( sampleTime ); - - Partial::iterator ret_pos = newp.insert( insertTime, newbp ); - - } - - // remove excess null Breakpoints at the ends of the newly-formed - // Partial, no simple way to anticipate these, without evaluating - // the timing envelope at all points. - // - // Also runs of nulls in the middle? - Partial::iterator it = newp.begin(); - while( it != newp.end() && 0 == it->amplitude() ) - { - ++it; - } - newp.erase( newp.begin(), it ); - - it = newp.end(); - while( it != newp.begin() && 0 == (--it)->amplitude() ) - { - } - if ( it != newp.end() ) - { - newp.erase( ++it, newp.end() ); - } - - // is this a good idea? generally not. - if ( phaseCorrect_ && ( 0 != newp.numBreakpoints() ) ) - { - fixFrequency( newp ); // use default maxFixPct - } - - // store the new Partial: - p = newp; - - debugger << "resampled Partial has " << p.numBreakpoints() - << " Breakpoints" << endl; -} - -// --------------------------------------------------------------------------- -// quantize -// --------------------------------------------------------------------------- -//! The Breakpoint times in the resampled Partial will comprise a -//! sparse sequence of integer multiples of the sampling interval, -//! beginning with the multiple nearest to the Partial's start time and -//! ending with the multiple nearest to the Partial's end time, and including -//! only multiples that are near to Breakpoint times in the original Partial. -//! Resampling is performed in-place. -//! -//! \param p is the Partial to resample -// -void Resampler::quantize( Partial & p ) const -{ - debugger << "quantizing Partial labeled " << p.label() - << " having " << p.numBreakpoints() - << " Breakpoints" << endl; - - // for phase-correct quantization, first make the phases correct by - // fixing them from the initial phase (ideally this should have - // no effect but there's no way to be phase-correct after quantization - // unless the phases start correct), then quantize the Breakpoint - // times, then afterwards, adjust the frequencies to match - // the interpolated phases: - if ( phaseCorrect_ ) - { - fixPhaseForward( p.begin(), --p.end() ); - } - - // create the new Partial: - Partial newp; - newp.setLabel( p.label() ); - - Partial::const_iterator iter = p.begin(); - while( iter != p.end() ) - { - const Breakpoint & bp = iter.breakpoint(); - double bpt = iter.time(); - - // find the nearest multiple of the quantization interval: - long qstep = long( 0.5 + ( bpt / interval_ ) ); - - long endstep = qstep-1; // guarantee first insertion - if ( newp.numBreakpoints() != 0 ) - { - endstep = long( 0.5 + ( newp.endTime() / interval_ ) ); - } - - // insert a new Breakpoint if it does not duplicate - // a previous insertion, or if it is a Null (needed - // for phase-correction): - if ( (endstep != qstep) || (0 == bp.amplitude()) ) - { - double qt = interval_ * qstep; - - // insert another Breakpoint and advance the Breakpoint - // iterator and the current time: - // - // sample the Partial with a long fade time so that - // the amplitudes at the ends keep their original values: - const double a_long_time = 1.; - Breakpoint newbp = p.parametersAt( qt, a_long_time ); - Partial::iterator new_pos = newp.insert( qt, newbp ); - - // tricky: if the quantized position (iter) is a null Breakpoint, - // we had better made the new position a null also, very important - // for making phase resets happen at synthesis time. - // - // Also, if new_pos is earlier than iter, the phase should be rolled - // back from iter, rather than interpolated. If new_pos is later - // than iter, then its phase will have been correctly interpolated. - if ( 0 == bp.amplitude() ) - { - new_pos.breakpoint().setAmplitude( 0 ); - - if ( new_pos.time() < bpt ) - { - double dp = phaseTravel( new_pos.breakpoint(), bp, - bpt - new_pos.time() ); - new_pos.breakpoint().setPhase( bp.phase() - dp ); - } - } - } - ++iter; - } - - // for phase-correct quantization, adjust the frequencies to match - // the interpolated phases: - if ( phaseCorrect_ ) - { - fixFrequency( newp, 5 ); - } - - - debugger << "quantized Partial has " << newp.numBreakpoints() - << " Breakpoints" << endl; - - // store the new Partial: - p = newp; -} - -// --------------------------------------------------------------------------- -// insert_resampled_at (helper) -// --------------------------------------------------------------------------- -// -static Partial::iterator -insert_resampled_at( Partial & newp, const Partial & p, - double sampleTime, double insertTime ) -{ - // make a resampled Breakpoint: - Breakpoint newbp = p.parametersAt( sampleTime ); - - // handle end points to reduce error at ends - if ( sampleTime < p.startTime() ) - { - newbp.setAmplitude( p.first().amplitude() ); - } - else if ( sampleTime > p.endTime() ) - { - newbp.setAmplitude( p.last().amplitude() ); - } - - - Partial::iterator ret_pos = newp.insert( insertTime, newbp ); - - debugger << "inserted Breakpoint having amplitude " << newbp.amplitude() - << " at time " << insertTime << endl; - - return ret_pos; -} - -} // end of namespace Loris - diff --git a/loris_library/Source/src/Resampler.h b/loris_library/Source/src/Resampler.h deleted file mode 100644 index bc45eb3..0000000 --- a/loris_library/Source/src/Resampler.h +++ /dev/null @@ -1,449 +0,0 @@ -#ifndef INCLUDE_RESAMPLER_H -#define INCLUDE_RESAMPLER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Resampler.h - * - * Definition of class Resampler, for converting reassigned Partial envelopes - * into more conventional additive synthesis envelopes, having data points - * at regular time intervals. The benefits of reassigned analysis are NOT - * lost in this process, since the elimination of unreliable data and the - * reduction of temporal smearing are reflected in the resampled data. - * - * Lippold, 7 Aug 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "PartialList.h" -#include "LinearEnvelope.h" - -// begin namespace -namespace Loris { - -class Partial; - -// --------------------------------------------------------------------------- -// class Resampler -// -//! Class Resampler represents an algorithm for resampling Partial envelopes -//! at regular time intervals. Resampling makes the envelope data more suitable -//! for exchange (as SDIF data, for example) with other applications that -//! cannot process raw (continuously-distributed) reassigned data. Resampling -//! will often greatly reduce the size of the data (by greatly reducing the -//! number of Breakpoints in the Partials) without adversely affecting the -//! quality of the reconstruction. -// -class Resampler -{ -// --- public interface --- -public: -// --- lifecycle --- - - //! Initialize a Resampler having the specified uniform sampling - //! interval. Enable phase-correct resampling, in which frequencies - //! of resampled Partials are modified (using fixFrequency) such - //! that the resampled phases are achieved in synthesis. Phase- - //! correct resampling can be disabled using setPhaseCorrect. - //! - //! Resampled Partials will be composed of Breakpoints at every - //! integer multiple of the resampling interval. - //! - //! \sa setPhaseCorrect - //! \sa fixFrequency - //! - //! \param sampleInterval is the resampling interval in seconds, - //! Breakpoint data is computed at integer multiples of - //! sampleInterval seconds. - //! - //! \throw InvalidArgument if sampleInterval is not positive. - explicit Resampler( double sampleInterval ); - - - // --- use compiler-generated copy/assign/destroy --- - -// --- parameters --- - - //! Specify phase-corrected resampling, or not. If phase - //! correct, Partial frequencies are altered slightly - //! to match, as nearly as possible, the Breakpoint - //! phases after resampling. Phases are updated so that - //! the Partial frequencies and phases are consistent after - //! resampling. - //! - //! \param correctPhase is a boolean flag specifying that - //! (if true) frequency/phase correction should be - //! applied after resampling. - void setPhaseCorrect( bool correctPhase ); - -// --- resampling --- - - //! Resample the specified Partial using the stored quanitization interval. - //! The Breakpoint times will comprise a contiguous sequence of all integer - //! multiples of the sampling interval, starting and ending with the nearest - //! multiples to the ends of the Partial. If phase correct resampling is - //! specified (the default)≤ frequencies and phases are corrected to be in - //! agreement and to match as nearly as possible the resampled phases. - //! - //! Resampling is performed in-place. - //! - //! \param p is the Partial to resample - void resample( Partial & p ) const; - - //! Function call operator: same as resample( p ). - void operator() ( Partial & p ) const - { - resample( p ); - } - - //! Resample the specified Partial using the stored quanitization interval. - //! The Breakpoint times will comprise a contiguous sequence of all integer - //! multiples of the sampling interval, starting and ending with the nearest - //! multiples to the ends of the Partial. If phase correct resampling is - //! specified (the default)≤ frequencies and phases are corrected to be in - //! agreement and to match as nearly as possible the resampled phases. - //! - //! The timing envelope represents a warping of the time axis that is - //! applied during resampling. The Breakpoint times in resampled Partials - //! will a comprise contiguous sequence of all integer multiples of the - //! sampling interval between the first and last breakpoints in the timing - //! envelope, and each Breakpoint will represent the parameters of the - //! original Partial at the time that is the value of the timing envelope - //! at that instant. - //! - //! Resampling is performed in-place. - //! - //! \param p is the Partial to resample - //! - //! \param timingEnv is the timing envelope, a map of Breakpoint - //! times in resampled Partials onto parameter sampling - //! instants in the original Partials. - //! - //! \throw InvalidArgument if timingEnv has any negative breakpoint - //! times or values. - void resample( Partial & p, const LinearEnvelope & timingEnv ) const; - - //! Quantize the Breakpoint times using the specified Partial using the - //! stored quanitization interval. Each Breakpoint in the Partial is - //! replaced by a Breakpoint constructed by resampling the Partial at - //! the nearest integer multiple of the of the resampling interval. - //! - //! Quantization is performed in-place. - //! - //! \param p is the Partial to resample - void quantize( Partial & p ) const; - - - //! Resample all Partials in the specified (half-open) range using this - //! Resampler's stored quanitization interval. The Breakpoint times in - //! resampled Partials will comprise a contiguous sequence of all integer - //! multiples of the sampling interval, starting and ending with the nearest - //! multiples to the ends of the Partial. If phase correct resampling is - //! specified (the default)≤ frequencies and phases are corrected to be in - //! agreement and to match as nearly as possible the resampled phases. - //! - //! Resampling is performed in-place. - //! - //! \param begin is the beginning of the range of Partials to resample - //! \param end is (one-past) the end of the range of Partials to resample - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void resample( Iter begin, Iter end ) const; -#else - inline - void resample( PartialList::iterator begin, PartialList::iterator end ) const; -#endif - - //! Function call operator: same as resample( begin, end ). -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void operator()( Iter begin, Iter end ) const -#else - void operator()( PartialList::iterator begin, PartialList::iterator end ) const -#endif - { - resample( begin, end ); - } - - //! Resample all Partials in the specified (half-open) range using this - //! Resampler's stored quanitization interval. The Breakpoint times in - //! resampled Partials will comprise a contiguous sequence of all integer - //! multiples of the sampling interval, starting and ending with the nearest - //! multiples to the ends of the Partial. If phase correct resampling is - //! specified (the default)≤ frequencies and phases are corrected to be in - //! agreement and to match as nearly as possible the resampled phases. - //! - //! The timing envelope represents a warping of the time axis that is - //! applied during resampling. The Breakpoint times in resampled Partials - //! will a comprise contiguous sequence of all integer multiples of the - //! sampling interval between the first and last breakpoints in the timing - //! envelope, and each Breakpoint will represent the parameters of the - //! original Partial at the time that is the value of the timing envelope - //! at that instant. - //! - //! Resampling is performed in-place. - //! - //! \param begin is the beginning of the range of Partials to resample - //! \param end is (one-past) the end of the range of Partials to resample - //! \param timingEnv is the timing envelope, a map of Breakpoint - //! times in resampled Partials onto parameter sampling - //! instants in the original Partials. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void resample( Iter begin, Iter end, const LinearEnvelope & timingEnv ) const; -#else - inline - void resample( PartialList::iterator begin, PartialList::iterator end, - const LinearEnvelope & timingEnv) const; -#endif - - //! Quantize all Partials in the specified (half-open) range. - //! Each Breakpoint in the Partials is replaced by a Breakpoint - //! constructed by resampling the Partial at the nearest - //! integer multiple of the of the resampling interval. - //! - //! \param begin is the beginning of the range of Partials to quantize - //! \param end is (one-past) the end of the range of Partials to quantize - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void quantize( Iter begin, Iter end ) const; -#else - inline - void quantize( PartialList::iterator begin, PartialList::iterator end ) const; -#endif - -// -- static members -- - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Resampler using the specified resampling - //! interval, and use it to channelize a sequence of Partials. - //! - //! \param begin is the beginning of a sequence of Partials to - //! resample. - //! \param end is the end of a sequence of Partials to - //! resample. - //! \param sampleInterval is the resampling interval in seconds, - //! Breakpoint data is computed at integer multiples of - //! sampleInterval seconds. - //! \param denseResampling is a boolean flag indicating that dense - //! resamping (Breakpoint at every integer multiple of the - //! resampling interval) should be performed. If false (the - //! default), sparse resampling (Breakpoints only at multiples - //! of the resampling interval near Breakpoint times in the - //! original Partial) is performed. - //! \throw InvalidArgument if sampleInterval is not positive. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - static - void resample( Iter begin, Iter end, double sampleInterval, - bool denseResampling = false ); -#else - static inline - void resample( PartialList::iterator begin, PartialList::iterator end, - double sampleInterval, bool denseResampling = false ); -#endif - -// --- instance variables --- -private: - - //! the resampling interval in seconds - double interval_; - - //! boolean flag selecting phase-corrected resampling - //! (default is true) - bool phaseCorrect_; - -}; // end of class Resampler - -// --------------------------------------------------------------------------- -// resample (sequence of Partials) -// --------------------------------------------------------------------------- -//! Resample all Partials in the specified (half-open) range using this -//! Resampler's stored sampling interval, so that the Breakpoints in -//! the Partial envelopes will all lie on a common temporal grid. -//! The Breakpoint times in the resampled Partial will comprise a -//! contiguous sequence of integer multiples of the sampling interval, -//! beginning with the multiple nearest to the Partial's start time and -//! ending with the multiple nearest to the Partial's end time. Resampling -//! is performed in-place. -//! -//! \param begin is the beginning of the range of Partials to resample -//! \param end is (one-past) the end of the range of Partials to resample -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Resampler::resample( Iter begin, Iter end ) const -#else -inline -void Resampler::resample( PartialList::iterator begin, PartialList::iterator end ) const -#endif -{ - while ( begin != end ) - { - resample( *begin++ ); - } -} - -// --------------------------------------------------------------------------- -// resample (sequence of Partials, with timing envelope) -// --------------------------------------------------------------------------- -//! Resample all Partials in the specified (half-open) range using this -//! Resampler's stored sampling interval, so that the Breakpoints in -//! the Partial envelopes will all lie on a common temporal grid. -//! The Breakpoint times in the resampled Partial will comprise a -//! contiguous sequence of integer multiples of the sampling interval, -//! beginning with the multiple nearest to the Partial's start time and -//! ending with the multiple nearest to the Partial's end time. Resampling -//! is performed in-place. -//! -//! \param begin is the beginning of the range of Partials to resample -//! \param end is (one-past) the end of the range of Partials to resample -//! \param timingEnv is the timing envelope, a map of Breakpoint -//! times in resampled Partials onto parameter sampling -//! instants in the original Partials. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Resampler::resample( Iter begin, Iter end, const LinearEnvelope & timingEnv ) const -#else -inline -void Resampler::resample( PartialList::iterator begin, PartialList::iterator end, - const LinearEnvelope & timingEnv ) const -#endif -{ - while ( begin != end ) - { - resample( *begin++, timingEnv ); - } -} - -// --------------------------------------------------------------------------- -// quantize (sequence of Partials) -// --------------------------------------------------------------------------- -//! Quantize all Partials in the specified (half-open) range. -//! Each Breakpoint in the Partials is replaced by a Breakpoint -//! constructed by resampling the Partial at the nearest -//! integer multiple of the of the resampling interval. -//! -//! \param begin is the beginning of the range of Partials to quantize -//! \param end is (one-past) the end of the range of Partials to quantize -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void Resampler::quantize( Iter begin, Iter end ) const -#else -inline -void Resampler::quantize( PartialList::iterator begin, PartialList::iterator end ) const -#endif -{ - while ( begin != end ) - { - quantize( *begin++ ); - } -} - - -// --------------------------------------------------------------------------- -// resample (static) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! phase-correct resampling to a sequence of Partials. -//! Construct a Resampler using the specified resampling -//! interval, and use it to channelize a sequence of Partials. -//! -//! \param begin is the beginning of a sequence of Partials to -//! resample. -//! \param end is the end of a sequence of Partials to -//! resample. -//! \param sampleInterval is the resampling interval in seconds, -//! Breakpoint data is computed at integer multiples of -//! sampleInterval seconds. -//! \param denseResampling is a boolean flag indicating that dense -//! resamping (Breakpoint at every integer multiple of the -//! resampling interval) should be performed. If false (the -//! default), sparse resampling (Breakpoints only at multiples -//! of the resampling interval near Breakpoint times in the -//! original Partial) is performed. -//! \throw InvalidArgument if sampleInterval is not positive. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Resampler::resample( Iter begin, Iter end, double sampleInterval, - bool denseResampling ) -#else -inline -void Resampler::resample( PartialList::iterator begin, PartialList::iterator end, - double sampleInterval, bool denseResampling ) -#endif -{ - Resampler instance( sampleInterval ); - - if ( denseResampling ) - { - instance.resample( begin, end ); - } - else - { - instance.quantize( begin, end ); - } -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_RESAMPLER_H */ - diff --git a/loris_library/Source/src/SdifFile.cpp b/loris_library/Source/src/SdifFile.cpp deleted file mode 100644 index 9ca879e..0000000 --- a/loris_library/Source/src/SdifFile.cpp +++ /dev/null @@ -1,2176 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SdifFile.C - * - * Implementation of class SdifFile, which reads and writes SDIF files. - * - * Lippold Haken, 4 July 2000, using CNMAT SDIF library - * Lippold Haken, 20 October 2000, using IRCAM SDIF library (tutorial by Diemo Schwarz) - * Lippold Haken, 22 December 2000, using 1LBL frames - * Lippold Haken, 27 March 2001, write only 7-column 1TRC, combine reading and writing classes - * Lippold Haken, 31 Jan 2002, write either 4-column 1TRC or 6-column RBEP - * Lippold Haken, 20 Apr 2004, back to using CNMAT SDIF library - * Lippold Haken, 06 Oct 2004, write 64-bit float files, read both 32-bit and 64-bit float - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -/* - -Portions of this code are from the CNMAT SDIF library. - -Copyright (c) 1996. 1997, 1998, 1999. The Regents of the University of California -(Regents). All Rights Reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation, without fee and without a signed licensing agreement, is hereby -granted, provided that the above copyright notice, this paragraph and the -following two paragraphs appear in all copies, modifications, and -distributions. Contact The Office of Technology Licensing, UC Berkeley, 2150 -Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, (510) 643-7201, for -commercial licensing opportunities. - -Written by Matt Wright, Amar Chaudhary, and Sami Khoury, The Center for New -Music and Audio Technologies, University of California, Berkeley. - - IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, - SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST - PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS - DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING - DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". - REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, - ENHANCEMENTS, OR MODIFICATIONS. - -SDIF spec: http://www.cnmat.berkeley.edu/SDIF/ - -*/ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "SdifFile.h" -#include "LorisExceptions.h" -#include "Notifier.h" -#include "Partial.h" -#include "PartialList.h" -#include "PartialPtrs.h" - -#include -#include -#include -#include -#include -#include - -#if HAVE_M_PI - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -using namespace std; - -// begin namespace -namespace Loris { - -// -- CNMAT SDIF definitions -- -// --------------------------------------------------------------------------- -// CNMAT SDIF types -// --------------------------------------------------------------------------- - -// try to use the information gathered by configure -- if not using -// config.h, then pick some (hopefully-) reasonable values for -// these things and hope for the best... -#if ! defined( SIZEOF_SHORT ) -#define SIZEOF_SHORT 2 -#endif - -#if ! defined( SIZEOF_INT ) -#define SIZEOF_INT 4 -#endif - -#if ! defined( SIZEOF_LONG ) -#define SIZEOF_LONG 4 -#endif - -#if defined(SIZEOF_SHORT) && (SIZEOF_SHORT == 2) -typedef unsigned short sdif_unicode; -typedef short sdif_int16; -#elif defined(SIZEOF_INT) && (SIZEOF_INT == 2) -typedef unsigned int sdif_unicode; -typedef int sdif_int16; -#else -#error "SdifFile.C: cannot identify a two-byte integer type, define SIZEOF_SHORT or SIZEOF_INT" -#endif - -#if defined(SIZEOF_INT) && (SIZEOF_INT == 4) -typedef int sdif_int32; -typedef unsigned int sdif_uint32; -#elif defined(SIZEOF_LONG) && (SIZEOF_LONG == 4) -typedef long sdif_int32; -typedef unsigned long sdif_uint32; -#else -#error "SdifFile.C: cannot identify a four-byte integer type, define SIZEOF_INT or SIZEOF_LONG" -#endif - -// It is probably an unnecessary nuisance to check these, since there's -// no alternative type to try. Requiring builders to define these -// symbols doesn't really serve any purpose. C++ doesn't provide a -// standard way to find a data type having a particular size -// (as stdint.h does for interger types in C99). -/* -#if SIZEOF_FLOAT == 4 -typedef float sdif_float32; -#else -#error "SdifFile.C: cannot identify a four-byte floating-point type" -#endif - -#if SIZEOF_DOUBLE == 8 -typedef double sdif_float64; -#else -#error "SdifFile.C: cannot identify a eight-byte floating-point type" -#endif -*/ -typedef float sdif_float32; -typedef double sdif_float64; - - - -// --------------------------------------------------------------------------- -// SDIF_GlobalHeader -// --------------------------------------------------------------------------- -typedef struct { - char SDIF[4]; /* must be 'S', 'D', 'I', 'F' */ - sdif_int32 size; /* size of header frame, not including SDIF or size. */ - sdif_int32 SDIFversion; - sdif_int32 SDIFStandardTypesVersion; -} SDIF_GlobalHeader; - -// --------------------------------------------------------------------------- -// SDIF_FrameHeader -// --------------------------------------------------------------------------- -typedef struct { - char frameType[4]; /* should be a registered frame type */ - sdif_int32 size; /* # bytes in this frame, not including - frameType or size */ - sdif_float64 time; /* time corresponding to frame */ - sdif_int32 streamID; /* frames that go together have the same ID */ - sdif_int32 matrixCount; /* number of matrices in frame */ -} SDIF_FrameHeader; - - -// --------------------------------------------------------------------------- -// SDIF_MatrixHeader -// --------------------------------------------------------------------------- -typedef struct { - char matrixType[4]; - sdif_int32 matrixDataType; - sdif_int32 rowCount; - sdif_int32 columnCount; -} SDIF_MatrixHeader; - - -/* Version numbers for SDIF_GlobalHeader associated with this library */ -#define SDIF_SPEC_VERSION 3 -#define SDIF_LIBRARY_VERSION 1 - -// --------------------------------------------------------------------------- -// Enumerations for type definitions in matrices. -// --------------------------------------------------------------------------- -typedef enum { - SDIF_FLOAT32 = 0x0004, - SDIF_FLOAT64 = 0x0008, - SDIF_INT16 = 0x0102, - SDIF_INT32 = 0x0104, - SDIF_INT64 = 0x0108, - SDIF_UINT32 = 0x0204, - SDIF_UTF8 = 0x0301, - SDIF_BYTE = 0x0401, - SDIF_NO_TYPE = -1 -} SDIF_MatrixDataType; - -typedef enum { - SDIF_FLOAT = 0, - SDIF_INT = 1, - SDIF_UINT = 2, - SDIF_TEXT = 3, - SDIF_ARBITRARY = 4 -} SDIF_MatrixDataTypeHighOrder; - -/* SDIF_GetMatrixDataTypeSize -- - Find the size in bytes of the data type indicated by "d" */ -#define SDIF_GetMatrixDataTypeSize(d) ((d) & 0xff) - -// -- CNMAT SDIF errors -- -// --------------------------------------------------------------------------- -// CNMAT SDIF error handling machinery. -// --------------------------------------------------------------------------- -typedef enum { - ESDIF_SUCCESS=0, - ESDIF_SEE_ERRNO=1, - ESDIF_BAD_SDIF_HEADER=2, - ESDIF_BAD_FRAME_HEADER=3, - ESDIF_SKIP_FAILED=4, - ESDIF_BAD_MATRIX_DATA_TYPE=5, - ESDIF_BAD_SIZEOF=6, - ESDIF_END_OF_DATA=7, /* Not necessarily an error */ - ESDIF_BAD_MATRIX_HEADER=8, - ESDIF_OBSOLETE_FILE_VERSION=9, - ESDIF_OBSOLETE_TYPES_VERSION=10, - ESDIF_WRITE_FAILED=11, - ESDIF_READ_FAILED=12, - ESDIF_OUT_OF_MEMORY=13, /* Used only by sdif-mem.c */ - ESDIF_DUPLICATE_MATRIX_TYPE_IN_FRAME=14 -} SDIFresult; -static const char *error_string_array[] = { - "Everything's cool", - "This program should display strerror(errno) instead of this string", - "Bad SDIF header", - "Frame header's size is too low for time tag and stream ID", - "fseek() failed while skipping over data", - "Unknown matrix data type encountered in SDIF_WriteFrame().", - (char *) NULL, /* this will be set by SizeofSanityCheck() */ - "End of data", - "Bad SDIF matrix header", - "Obsolete SDIF file from an old version of SDIF", - "Obsolete version of the standard SDIF frame and matrix types", - "I/O error: couldn't write", - "I/O error: couldn't read", - "Out of memory", - "Frame has two matrices with the same MatrixType" -}; - -// -- CNMAT SDIF endian -- -// --------------------------------------------------------------------------- -// CNMAT SDIF little endian machinery. -// --------------------------------------------------------------------------- - -// WORDS_BIGENDIAN is defined (or not) in config.h, determined -// at configure-time, changed from test of LITTLE_ENDIAN -// which might be erroneously defined in some standard header. - -// If we didn't run configure, try to make a good guess. -#if !(HAVE_CONFIG_H) && !defined(WORDS_BIGENDIAN) - #if (defined(__ppc__) || defined(__ppc64__)) - #define WORDS_BIGENDIAN 1 - #else - #undef WORDS_BIGENDIAN - #endif -#endif - -#if !defined(WORDS_BIGENDIAN) -#define BUFSIZE 4096 -static char p[BUFSIZE]; -#endif - - -static SDIFresult SDIF_Write1(const void *block, size_t n, FILE *f) { - return (fwrite (block,1,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; -} - - -static SDIFresult SDIF_Write2(const void *block, size_t n, FILE *f) { -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - const char *q = (const char *)block; - int i, m = 2*n; - - if ((n << 1) > BUFSIZE) { - /* Too big for buffer */ - int num = BUFSIZE >> 1; - if (r = SDIF_Write2(block, num, f)) return r; - return SDIF_Write2(((char *) block) + (num<<1), n-num, f); - } - - for (i = 0; i < m; i += 2) { - p[i] = q[i+1]; - p[i+1] = q[i]; - } - - return (fwrite(p,2,n,f)==n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; - -#else - return (fwrite (block,2,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; -#endif -} - - - -static SDIFresult SDIF_Write4(const void *block, size_t n, FILE *f) { -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - const char *q = (const char *)block; - int i, m = 4*n; - - if ((n << 2) > BUFSIZE) - { - int num = BUFSIZE >> 2; - if (r = SDIF_Write4(block, num, f)) return r; - return SDIF_Write4(((char *) block) + (num<<2), n-num, f); - } - - for (i = 0; i < m; i += 4) - { - p[i] = q[i+3]; - p[i+3] = q[i]; - p[i+1] = q[i+2]; - p[i+2] = q[i+1]; - } - - return (fwrite(p,4,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; -#else - return (fwrite(block,4,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; -#endif -} - - - -static SDIFresult SDIF_Write8(const void *block, size_t n, FILE *f) { -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - const char *q = (const char *)block; - int i, m = 8*n; - - if ((n << 3) > BUFSIZE) { - int num = BUFSIZE >> 3; - if (r = SDIF_Write8(block, num, f)) return r; - return SDIF_Write8(((char *) block) + (num<<3), n-num, f); - } - - for (i = 0; i < m; i += 8) { - p[i] = q[i+7]; - p[i+7] = q[i]; - p[i+1] = q[i+6]; - p[i+6] = q[i+1]; - p[i+2] = q[i+5]; - p[i+5] = q[i+2]; - p[i+3] = q[i+4]; - p[i+4] = q[i+3]; - } - - return (fwrite(p,8,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; -#else - return (fwrite(block,8,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; -#endif -} - - -static SDIFresult SDIF_Read1(void *block, size_t n, FILE *f) { - return (fread (block,1,n,f) == n) ? ESDIF_SUCCESS : ESDIF_READ_FAILED; -} - - -static SDIFresult SDIF_Read2(void *block, size_t n, FILE *f) { - -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - char *q = (char *)block; - int i, m = 2*n; - - if ((n << 1) > BUFSIZE) { - int num = BUFSIZE >> 1; - if (r = SDIF_Read2(block, num, f)) return r; - return SDIF_Read2(((char *) block) + (num<<1), n-num, f); - } - - if (fread(p,2,n,f) != n) return ESDIF_READ_FAILED; - - for (i = 0; i < m; i += 2) { - q[i] = p[i+1]; - q[i+1] = p[i]; - } - - return ESDIF_SUCCESS; -#else - return (fread(block,2,n,f) == n) ? ESDIF_SUCCESS : ESDIF_READ_FAILED; -#endif - -} - - -static SDIFresult SDIF_Read4(void *block, size_t n, FILE *f) { -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - char *q = (char *)block; - int i, m = 4*n; - - if ((n << 2) > BUFSIZE) { - int num = BUFSIZE >> 2; - if (r = SDIF_Read4(block, num, f)) return r; - return SDIF_Read4(((char *) block) + (num<<2), n-num, f); - } - - if (fread(p,4,n,f) != n) return ESDIF_READ_FAILED; - - for (i = 0; i < m; i += 4) { - q[i] = p[i+3]; - q[i+3] = p[i]; - q[i+1] = p[i+2]; - q[i+2] = p[i+1]; - } - - return ESDIF_SUCCESS; - -#else - return (fread(block,4,n,f) == n) ? ESDIF_SUCCESS : ESDIF_READ_FAILED; -#endif - -} - - -static SDIFresult SDIF_Read8(void *block, size_t n, FILE *f) { -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - char *q = (char *)block; - int i, m = 8*n; - - if ((n << 3) > BUFSIZE) { - int num = BUFSIZE >> 3; - if (r = SDIF_Read8(block, num, f)) return r; - return SDIF_Read8(((char *) block) + (num<<3), n-num, f); - } - - if (fread(p,8,n,f) != n) return ESDIF_READ_FAILED; - - for (i = 0; i < m; i += 8) { - q[i] = p[i+7]; - q[i+7] = p[i]; - q[i+1] = p[i+6]; - q[i+6] = p[i+1]; - q[i+2] = p[i+5]; - q[i+5] = p[i+2]; - q[i+3] = p[i+4]; - q[i+4] = p[i+3]; - } - - return ESDIF_SUCCESS; - -#else - return (fread(block,8,n,f) == n) ? ESDIF_SUCCESS : ESDIF_READ_FAILED; -#endif -} - -// -- CNMAT SDIF intialization -- -// --------------------------------------------------------------------------- -// CNMAT SDIF initialization. -// --------------------------------------------------------------------------- -static int SizeofSanityCheck(void) { - int OK = 1; - static char errorMessage[sizeof("sizeof(sdif_float64) is 999!!!")]; - - if (sizeof(sdif_int16) != 2) { - sprintf(errorMessage, "sizeof(sdif_int16) is %d!", (int)sizeof(sdif_int16)); - OK = 0; - } - - if (sizeof(sdif_int32) != 4) { - sprintf(errorMessage, "sizeof(sdif_int32) is %d!", (int)sizeof(sdif_int32)); - OK = 0; - } - - if (sizeof(sdif_float32) != 4) { - sprintf(errorMessage, "sizeof(sdif_float32) is %d!", (int)sizeof(sdif_float32)); - OK = 0; - } - - if (sizeof(sdif_float64) != 8) { - sprintf(errorMessage, "sizeof(sdif_float64) is %d!", (int)sizeof(sdif_float64)); - OK = 0; - } - - if (!OK) { - error_string_array[ESDIF_BAD_SIZEOF] = errorMessage; - } - return OK; -} - - - -static SDIFresult SDIF_Init(void) { - if (!SizeofSanityCheck()) { - return ESDIF_BAD_SIZEOF; - } - return ESDIF_SUCCESS; -} - -// -- CNMAT SDIF frame header -- -// --------------------------------------------------------------------------- -// CNMAT SDIF frame headers. -// --------------------------------------------------------------------------- -static void SDIF_Copy4Bytes(char *target, const char *string) { - target[0] = string[0]; - target[1] = string[1]; - target[2] = string[2]; - target[3] = string[3]; -} - -static int SDIF_Char4Eq(const char *ths, const char *that) { - return ths[0] == that[0] && ths[1] == that[1] && - ths[2] == that[2] && ths[3] == that[3]; -} - -static void SDIF_FillGlobalHeader(SDIF_GlobalHeader *h) { - SDIF_Copy4Bytes(h->SDIF, "SDIF"); - h->size = 8; - h->SDIFversion = SDIF_SPEC_VERSION; - h->SDIFStandardTypesVersion = SDIF_LIBRARY_VERSION; -} - -static SDIFresult SDIF_WriteGlobalHeader(const SDIF_GlobalHeader *h, FILE *f) { -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - if (r = SDIF_Write1(&(h->SDIF), 4, f)) return r; - if (r = SDIF_Write4(&(h->size), 1, f)) return r; - if (r = SDIF_Write4(&(h->SDIFversion), 1, f)) return r; - if (r = SDIF_Write4(&(h->SDIFStandardTypesVersion), 1, f)) return r; - return ESDIF_SUCCESS; -#else - - return (fwrite(h, sizeof(*h), 1, f) == 1) ?ESDIF_SUCCESS:ESDIF_WRITE_FAILED; - -#endif -} - -static SDIFresult SDIF_ReadFrameHeader(SDIF_FrameHeader *fh, FILE *f) { -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - - if (SDIF_Read1(&(fh->frameType),4,f)) { - if (feof(f)) { - return ESDIF_END_OF_DATA; - } - return ESDIF_READ_FAILED; - } - if (r = SDIF_Read4(&(fh->size),1,f)) return r; - if (r = SDIF_Read8(&(fh->time),1,f)) return r; - if (r = SDIF_Read4(&(fh->streamID),1,f)) return r; - if (r = SDIF_Read4(&(fh->matrixCount),1,f)) return r; - return ESDIF_SUCCESS; -#else - size_t amount_read; - - amount_read = fread(fh, sizeof(*fh), 1, f); - if (amount_read == 1) return ESDIF_SUCCESS; - if (amount_read == 0) { - /* Now that fread failed, maybe we're at EOF. */ - if (feof(f)) { - return ESDIF_END_OF_DATA; - } - } - return ESDIF_READ_FAILED; -#endif /* ! WORDS_BIGENDIAN */ -} - - -static SDIFresult SDIF_WriteFrameHeader(const SDIF_FrameHeader *fh, FILE *f) { - -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - - if (r = SDIF_Write1(&(fh->frameType),4,f)) return r; - if (r = SDIF_Write4(&(fh->size),1,f)) return r; - if (r = SDIF_Write8(&(fh->time),1,f)) return r; - if (r = SDIF_Write4(&(fh->streamID),1,f)) return r; - if (r = SDIF_Write4(&(fh->matrixCount),1,f)) return r; -#ifdef __WIN32__ - fflush(f); -#endif - return ESDIF_SUCCESS; -#else - - return (fwrite(fh, sizeof(*fh), 1, f) == 1)?ESDIF_SUCCESS:ESDIF_WRITE_FAILED; - -#endif -} - -static SDIFresult SkipBytes(FILE *f, int bytesToSkip) { -#ifdef STREAMING - /* Can't fseek in a stream, so waste some time needlessly copying - some bytes in memory */ - { -#define BLOCK_SIZE 1024 - char buf[BLOCK_SIZE]; - while (bytesToSkip > BLOCK_SIZE) - { - if (fread (buf, BLOCK_SIZE, 1, f) != 1) - { - return ESDIF_READ_FAILED; - } - bytesToSkip -= BLOCK_SIZE; - } - - if (fread (buf, bytesToSkip, 1, f) != 1) - { - return ESDIF_READ_FAILED; - } - } -#else - /* More efficient implementation */ - if (fseek(f, bytesToSkip, SEEK_CUR) != 0) - { - return ESDIF_SKIP_FAILED; - } -#endif - return ESDIF_SUCCESS; -} - -static SDIFresult SDIF_SkipFrame(const SDIF_FrameHeader *head, FILE *f) { - /* The header's size count includes the 8-byte time tag, 4-byte - stream ID and 4-byte matrix count that we already read. */ - int bytesToSkip = head->size - 16; - - if (bytesToSkip < 0) { - return ESDIF_BAD_FRAME_HEADER; - } - - return SkipBytes(f, bytesToSkip); -} - -// -- CNMAT SDIF matrix header -- -// --------------------------------------------------------------------------- -// CNMAT SDIF matrix headers. -// --------------------------------------------------------------------------- -static SDIFresult SDIF_ReadMatrixHeader(SDIF_MatrixHeader *m, FILE *f) { -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - if (r = SDIF_Read1(&(m->matrixType),4,f)) return r; - if (r = SDIF_Read4(&(m->matrixDataType),1,f)) return r; - if (r = SDIF_Read4(&(m->rowCount),1,f)) return r; - if (r = SDIF_Read4(&(m->columnCount),1,f)) return r; - return ESDIF_SUCCESS; -#else - if (fread(m, sizeof(*m), 1, f) == 1) { - return ESDIF_SUCCESS; - } else { - return ESDIF_READ_FAILED; - } -#endif - -} - -static SDIFresult SDIF_WriteMatrixHeader(const SDIF_MatrixHeader *m, FILE *f) { -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - if (r = SDIF_Write1(&(m->matrixType),4,f)) return r; - if (r = SDIF_Write4(&(m->matrixDataType),1,f)) return r; - if (r = SDIF_Write4(&(m->rowCount),1,f)) return r; - if (r = SDIF_Write4(&(m->columnCount),1,f)) return r; - return ESDIF_SUCCESS; -#else - return (fwrite(m, sizeof(*m), 1, f) == 1) ? ESDIF_SUCCESS:ESDIF_READ_FAILED; -#endif -} - - -static int SDIF_GetMatrixDataSize(const SDIF_MatrixHeader *m) { - int size; - size = SDIF_GetMatrixDataTypeSize(m->matrixDataType) * - m->rowCount * m->columnCount; - - if ((size % 8) != 0) { - size += (8 - (size % 8)); - } - - return size; -} - -static int SDIF_PaddingRequired(const SDIF_MatrixHeader *m) { - int size; - size = SDIF_GetMatrixDataTypeSize(m->matrixDataType) * - m->rowCount * m->columnCount; - - if ((size % 8) != 0) { - return (8 - (size % 8)); - } else { - return 0; - } -} - -// -- CNMAT SDIF matrix data -- -// --------------------------------------------------------------------------- -// CNMAT SDIF matrix data. -// --------------------------------------------------------------------------- -static SDIFresult SDIF_SkipMatrix(const SDIF_MatrixHeader *head, FILE *f) { - int size = SDIF_GetMatrixDataSize(head); - - if (size < 0) { - return ESDIF_BAD_MATRIX_HEADER; - } - - return SkipBytes(f, size); -} - - -static SDIFresult SDIF_WriteMatrixPadding(FILE *f, const SDIF_MatrixHeader *head) { - int paddingBytes; - sdif_int32 paddingBuffer[2] = {0,0}; - SDIFresult r; - - paddingBytes = SDIF_PaddingRequired(head); - if ((r = SDIF_Write1(paddingBuffer, paddingBytes, f))) return r; - - return ESDIF_SUCCESS; -} - - -static SDIFresult SDIF_WriteMatrixData(FILE *f, const SDIF_MatrixHeader *head, void *data) { - size_t datumSize = (size_t) SDIF_GetMatrixDataTypeSize(head->matrixDataType); - size_t numItems = (size_t) (head->rowCount * head->columnCount); - -#if !defined(WORDS_BIGENDIAN) - SDIFresult r; - switch (datumSize) { - case 1: - if (r = SDIF_Write1(data, numItems, f)) return r; - break; - case 2: - if (r = SDIF_Write2(data, numItems, f)) return r; - break; - case 4: - if (r = SDIF_Write4(data, numItems, f)) return r; - break; - case 8: - if (r = SDIF_Write8(data, numItems, f)) return r; - break; - default: - return ESDIF_BAD_MATRIX_DATA_TYPE; - } -#else - if (fwrite(data, datumSize, numItems, f) != numItems) { - return ESDIF_READ_FAILED; - } -#endif - - /* Handle padding */ - return SDIF_WriteMatrixPadding(f, head); -} - -// -- CNMAT SDIF open and close -- -// --------------------------------------------------------------------------- -// CNMAT SDIF file open and close. -// --------------------------------------------------------------------------- - -static SDIFresult SDIF_BeginWrite(FILE *output) { - SDIF_GlobalHeader h; - - SDIF_FillGlobalHeader(&h); - return SDIF_WriteGlobalHeader(&h, output); -} - -static SDIFresult SDIF_OpenWrite(const char *filename, FILE **resultp) { - FILE *result; - SDIFresult r; - - if ((result = fopen(filename, "wb")) == NULL) - { - return ESDIF_SEE_ERRNO; - } - if ((r = SDIF_BeginWrite(result))) - { - fclose(result); - return r; - } - *resultp = result; - return ESDIF_SUCCESS; -} - -static SDIFresult SDIF_CloseWrite(FILE *f) { - fflush(f); - if (fclose(f) == 0) { - return ESDIF_SUCCESS; - } else { - return ESDIF_SEE_ERRNO; - } -} - -static SDIFresult SDIF_BeginRead(FILE *input) { - SDIF_GlobalHeader sgh; - SDIFresult r; - - /* make sure the header is OK. */ - if ((r = SDIF_Read1(sgh.SDIF, 4, input))) return r; - if (!SDIF_Char4Eq(sgh.SDIF, "SDIF")) return ESDIF_BAD_SDIF_HEADER; - if ((r = SDIF_Read4(&sgh.size, 1, input))) return r; - if (sgh.size % 8 != 0) return ESDIF_BAD_SDIF_HEADER; - if (sgh.size < 8) return ESDIF_BAD_SDIF_HEADER; - if ((r = SDIF_Read4(&sgh.SDIFversion, 1, input))) return r; - if ((r = SDIF_Read4(&sgh.SDIFStandardTypesVersion, 1, input))) return r; - - if (sgh.SDIFversion < 3) { - return ESDIF_OBSOLETE_FILE_VERSION; - } - - if (sgh.SDIFStandardTypesVersion < 1) { - return ESDIF_OBSOLETE_TYPES_VERSION; - } - - /* skip size-8 bytes. (We already read the first two version numbers, - but maybe there's more data in the header frame.) */ - - if (sgh.size == 8) { - return ESDIF_SUCCESS; - } - - if (SkipBytes(input, sgh.size-8)) { - return ESDIF_BAD_SDIF_HEADER; - } - - return ESDIF_SUCCESS; -} - -static SDIFresult SDIF_OpenRead(const char *filename, FILE **resultp) { - FILE *result = NULL; - SDIFresult r; - - if ((result = fopen(filename, "rb")) == NULL) { - return ESDIF_SEE_ERRNO; - } - - if ((r = SDIF_BeginRead(result))) { - fclose(result); - return r; - } - - *resultp = result; - return ESDIF_SUCCESS; -} - -static SDIFresult SDIF_CloseRead(FILE *f) { - if (fclose(f) == 0) { - return ESDIF_SUCCESS; - } else { - return ESDIF_SEE_ERRNO; - } -} - -// -- construction -- - -// --------------------------------------------------------------------------- -// SdifFile construction helpers -// --------------------------------------------------------------------------- - -// import_sdif reads SDIF data from the specified file path and -// stores data in its PartialList and MarkerContainer arguments. -static void import_sdif( const std::string &, SdifFile::partials_type &, - SdifFile::markers_type & ); - -// export_sdif writes the data in its PartialList and MarkerContainer -// arguments to a specified SDIF file path. Writes bandwidth-enhanced -// Partials if enhanced is true, otherwise writes sinusoidal partials. -static void export_sdif( const std::string &, const SdifFile::partials_type &, - const SdifFile::markers_type &, bool enhanced ); - -// --------------------------------------------------------------------------- -// SdifFile constructor from filename -// --------------------------------------------------------------------------- -// Initialize an instance of SdifFile by importing Partial data from -// from the file having the specified filename or path. -// -SdifFile::SdifFile( const std::string & filename ) -{ - import_sdif( filename, partials_, markers_ ); -} - -// --------------------------------------------------------------------------- -// SdifFile constructor, empty -// --------------------------------------------------------------------------- -// Initialize an empty instance of SdifFile having no Partials. -// -SdifFile::SdifFile( void ) -{ -} - -// -- access -- -// --------------------------------------------------------------------------- -// markers -// --------------------------------------------------------------------------- -// Return a reference to the MarkerContainer (see Marker.h) for this SdifFile. -SdifFile::markers_type & SdifFile::markers( void ) -{ - return markers_; -} - -const SdifFile::markers_type & SdifFile::markers( void ) const -{ - return markers_; -} - -// --------------------------------------------------------------------------- -// partials -// --------------------------------------------------------------------------- -// Return a reference (or const reference) to the bandwidth-enhanced -// Partials represented by the envelope parameter streams in this SdifFile. -SdifFile::partials_type & SdifFile::partials( void ) -{ - return partials_; -} - -const SdifFile::partials_type & SdifFile::partials( void ) const -{ - return partials_; -} - -// -- mutation -- -// --------------------------------------------------------------------------- -// addPartial -// --------------------------------------------------------------------------- -// Add a copy of the specified Partial to this SdifFile. -// -// This member exists only for consistency with other File I/O -// classes in Loris. The same operation can be achieved by directly -// accessing the PartialList. -// -void SdifFile::addPartial( const Loris::Partial & p ) -{ - partials_.push_back( p ); -} - -// --------------------------------------------------------------------------- -// write (to path) -// --------------------------------------------------------------------------- -// Export the envelope Partials represented by this SdifFile to -// the file having the specified filename or path. -// -void SdifFile::write( const std::string & path ) -{ - export_sdif( path, partials_, markers_, true ); -} - -// --------------------------------------------------------------------------- -// write (to path) -// --------------------------------------------------------------------------- -// Export the envelope Partials represented by this SdifFile to -// the file having the specified filename or path in the 1TRC -// format, resampled, and without phase or bandwidth information. -// -void SdifFile::write1TRC( const std::string & path ) -{ - export_sdif( path, partials_, markers_, false ); -} - - -// -- Loris SDIF definitions -- -// --------------------------------------------------------------------------- -// Loris SDIF types -// --------------------------------------------------------------------------- -// Row of matrix data in SDIF RBEP, 1TRC, or RBEL format. -// -// The RBEP matrices are for reassigned bandwidth enhanced partials (in 6 columns). -// The 1TRC matrices are for sine-only partials (in 4 columns). -// The first four columns of an RBEP matrix correspond to the 4 columns in 1TRC. -// In the past, Loris exported a 7-column 1TRC; this is no longer exported, but can be imported. -// -// The RBEL format always has two columns, index and partial label. -// The RBEL matrix is optional; it has partial label information (in 2 columns). -int lorisRowMaxElements = 7; -int lorisRowEnhancedElements = 6; -int lorisRowSineOnlyElements = 4; - -typedef struct { - sdif_float64 index, freqOrLabel, amp, phase, noise, timeOffset, resampledFlag; -} RowOfLorisData64; - -typedef struct { - sdif_float32 index, freqOrLabel, amp, phase, noise, timeOffset, resampledFlag; -} RowOfLorisData32; - - -// SDIF signatures used by Loris. -typedef char sdif_signature[4]; -static sdif_signature lorisEnhancedSignature = { 'R','B','E','P' }; -static sdif_signature lorisLabelsSignature = { 'R','B','E','L' }; -static sdif_signature lorisSineOnlySignature = { '1','T','R','C' }; -static sdif_signature lorisMarkersSignature = { 'R','B','E','M' }; - - -// Exception class for handling errors in SDIF library: -class SdifLibraryError : public FileIOException -{ -public: - SdifLibraryError( const std::string & str, const std::string & where = "" ) : - FileIOException( std::string("SDIF library error -- ").append( str ), where ) {} -}; // end of class SdifLibraryError - -// macro to check for SDIF library errors and throw exceptions when -// they occur, which we really ought to do after every SDIF library -// call: -#define ThrowIfSdifError( errNum, report ) \ - if (errNum) \ - { \ - const char* errPtr = error_string_array[errNum]; \ - if (errPtr) \ - { \ - debugger << "SDIF error " << errPtr << endl; \ - std::string s(report); \ - s.append(", SDIF error message: "); \ - s.append(errPtr); \ - Throw( SdifLibraryError, s ); \ - } \ - } - -// -- SDIF reading helpers -- -// --------------------------------------------------------------------------- -// processRow64 -// --------------------------------------------------------------------------- -// Add to existing Loris partials, or create new Loris partials for this data. -// -static void -processRow64( const sdif_signature msig, const RowOfLorisData64 & rowData, const double frameTime, - std::vector< Partial > & partialsVector ) -{ - -// -// Skip this if the data point is not from the original data (7-column 1TRC format). -// - if (rowData.resampledFlag) - return; - -// -// Make sure we have enough partials for this partial's index. -// - if (partialsVector.size() <= rowData.index) - { - partialsVector.resize( long(rowData.index) + 500 ); - } - -// -// Create a new breakpoint and insert it. -// - if (SDIF_Char4Eq(msig, lorisEnhancedSignature) || SDIF_Char4Eq(msig, lorisSineOnlySignature)) - { - Breakpoint newbp( rowData.freqOrLabel, rowData.amp, rowData.noise, rowData.phase ); - partialsVector[long(rowData.index)].insert( frameTime + rowData.timeOffset, newbp ); - } -// -// Set partial label. -// - else if (SDIF_Char4Eq(msig, lorisLabelsSignature)) - { - partialsVector[long(rowData.index)].setLabel( (int) rowData.freqOrLabel ); - } - -} - -// --------------------------------------------------------------------------- -// processRow32 -// --------------------------------------------------------------------------- -// Add to existing Loris partials, or create new Loris partials for this data. -// This is for reading 32-bit float files. -// -static void -processRow32( const sdif_signature msig, const RowOfLorisData32 & rowData, const double frameTime, - std::vector< Partial > & partialsVector ) -{ - -// -// Skip this if the data point is not from the original data (7-column 1TRC format). -// - if (rowData.resampledFlag) - return; - -// -// Make sure we have enough partials for this partial's index. -// - if (partialsVector.size() <= rowData.index) - { - partialsVector.resize( long(rowData.index) + 500 ); - } - -// -// Create a new breakpoint and insert it. -// - if (SDIF_Char4Eq(msig, lorisEnhancedSignature) || SDIF_Char4Eq(msig, lorisSineOnlySignature)) - { - Breakpoint newbp( rowData.freqOrLabel, rowData.amp, rowData.noise, rowData.phase ); - partialsVector[long(rowData.index)].insert( frameTime + rowData.timeOffset, newbp ); - } -// -// Set partial label. -// - else if (SDIF_Char4Eq(msig, lorisLabelsSignature)) - { - partialsVector[long(rowData.index)].setLabel( (int) rowData.freqOrLabel ); - } - -} - -// --------------------------------------------------------------------------- -// readMarkers -// --------------------------------------------------------------------------- -// -static void -readMarkers( FILE * file, SDIF_FrameHeader fh, SdifFile::markers_type & markersVector ) -{ -// -// Read Loris markers from SDIF file in a RBEM frame. -// This precedes the envelope data in the file. -// Let exceptions propagate. -// - SDIFresult ret; - int cols = 1; -// -// The frame must contain exactly two matrices. -// - if (fh.matrixCount != 2) - { - Throw( FileIOException, "Markers frame has bad format." ); - } - -// -// Read the numeric (marker times) matrix. -// - { - SDIF_MatrixHeader mh; - ret = SDIF_ReadMatrixHeader(&mh,file); - ThrowIfSdifError( ret, "Error reading SDIF file" ); - - // Error if matrix has unexpected data type. - if ((mh.matrixDataType != SDIF_FLOAT32 && mh.matrixDataType != SDIF_FLOAT64) || mh.columnCount != cols) - { - Throw( FileIOException, "Markers frame has bad format." ); - } - - // Read each row of matrix data. - for (int row = 0; row < mh.rowCount; row++) - { - if (mh.matrixDataType == SDIF_FLOAT64) - { - sdif_float64 markerTime64; - SDIF_Read8(&markerTime64,1,file); - markersVector.push_back(Marker(markerTime64, "")); - } - else - { - sdif_float32 markerTime32; - SDIF_Read4(&markerTime32,1,file); - markersVector.push_back(Marker(markerTime32, "")); - } - } - - // Skip over padding, if any. - if ((mh.matrixDataType == SDIF_FLOAT32) && ((mh.rowCount * mh.columnCount) & 0x1)) - { - sdif_float32 pad; - SDIF_Read4(&pad,1,file); - } - } - -// -// Read the string (marker names) matrix. -// - { - SDIF_MatrixHeader mh; - ret = SDIF_ReadMatrixHeader(&mh,file); - ThrowIfSdifError( ret, "Error reading SDIF file" ); - - // Error if matrix has unexpected data type. - if (mh.matrixDataType != SDIF_UTF8 || mh.columnCount != cols) - { - Throw( FileIOException, "Markers frame has bad format." ); - } - - // Read strings. - std::string markerName; - int markerNumber = 0; - for (int row = 0; row < mh.rowCount; row++) - { - char ch; - SDIF_Read1(&ch,1,file); - - // If we have reached the end of a name, assign it to a marker. - if (ch == '\0') - { - // Save the name of the marker. - markersVector[markerNumber].setName(markerName); - - // Prepare to get name of next marker. - markerNumber++; - if (markerNumber > markersVector.size()) - { - Throw( FileIOException, "Markers frame has bad format." ); - } - markerName.erase(); - } - else - { - markerName += ch; - } - } - - // There should be one marker name for each marker time. - if (markerNumber != markersVector.size()) - { - Throw( FileIOException, "Markers frame has bad format." ); - } - - // Skip padding. - ret = SkipBytes(file, SDIF_PaddingRequired(&mh)); - } -} - -// --------------------------------------------------------------------------- -// readLorisMatrices -// --------------------------------------------------------------------------- -// Let exceptions propagate. -// -static void -readLorisMatrices( FILE *file, std::vector< Partial > & partialsVector, SdifFile::markers_type & markersVector ) -{ - SDIFresult ret; - -// -// Read all frames matching the file selection. -// - SDIF_FrameHeader fh; - while (!(ret = SDIF_ReadFrameHeader(&fh, file))) - { - - // Check for Loris Markers frame. - if (SDIF_Char4Eq(fh.frameType, lorisMarkersSignature)) - { - readMarkers( file, fh, markersVector ); - continue; - } - - // Skip frames until we find one we are interested in. - if (!SDIF_Char4Eq(fh.frameType, lorisEnhancedSignature) - && !SDIF_Char4Eq(fh.frameType, lorisSineOnlySignature) - && !SDIF_Char4Eq(fh.frameType, lorisLabelsSignature)) - { - ret = SDIF_SkipFrame(&fh, file); - ThrowIfSdifError( ret, "Error reading SDIF file" ); - continue; - } - - - // Read all matrices in this frame. - for (int m = 0; m < fh.matrixCount; m++) - { - SDIF_MatrixHeader mh; - ret = SDIF_ReadMatrixHeader(&mh,file); - ThrowIfSdifError( ret, "Error reading SDIF file" ); - - // Skip matrix if it has unexpected data type. - if ((mh.matrixDataType != SDIF_FLOAT32 && mh.matrixDataType != SDIF_FLOAT64) - || mh.columnCount > lorisRowMaxElements) - { - ret = SDIF_SkipMatrix(&mh, file); - ThrowIfSdifError( ret, "Error reading SDIF file" ); - continue; - } - - // Read each row of matrix data. - for (int row = 0; row < mh.rowCount; row++) - { - - if (mh.matrixDataType == SDIF_FLOAT64) - { - // Fill a rowData structure with one row from the matrix. - RowOfLorisData64 rowData64 = { 0.0 }; - sdif_float64 *rowDataPtr = &rowData64.index; - for (int col = 1; col <= mh.columnCount; col++) - { - SDIF_Read8(rowDataPtr++,1,file); - } - - // Add rowData as a new breakpoint in a partial, or, - // if its a RBEL matrix, read label mapping. - processRow64(mh.matrixType, rowData64, fh.time, partialsVector); - } - else - { - // Fill a rowData structure with one row from the matrix. - RowOfLorisData32 rowData32 = { 0.0 }; - sdif_float32 *rowDataPtr = &rowData32.index; - for (int col = 1; col <= mh.columnCount; col++) - { - SDIF_Read4(rowDataPtr++,1,file); - } - - // Add rowData as a new breakpoint in a partial, or, - // if its a RBEL matrix, read label mapping. - processRow32(mh.matrixType, rowData32, fh.time, partialsVector); - } - } - - // Skip over padding, if any. - if ((mh.matrixDataType == SDIF_FLOAT32) && ((mh.rowCount * mh.columnCount) & 0x1)) - { - sdif_float32 pad; - SDIF_Read4(&pad,1,file); - } - } - } - - // At this point, ret should be ESDIF_END_OF_DATA. - if (ret != ESDIF_END_OF_DATA) - ThrowIfSdifError( ret, "Error reading SDIF file" ); -} - -// --------------------------------------------------------------------------- -// read -// --------------------------------------------------------------------------- -// Let exceptions propagate. -// -static void import_sdif( const std::string &infilename, - SdifFile::partials_type & partials, - SdifFile::markers_type & markers) -{ - -// -// Initialize CNMSAT SDIF routines. -// - SDIFresult ret = SDIF_Init(); - if (ret) - { - Throw( FileIOException, "Could not initialize SDIF routines." ); - } - -// -// Open SDIF file for reading. -// Note: Currently we do not specify any selection criterion in this call. -// - FILE *file; - ret = SDIF_OpenRead(infilename.c_str(), &file); - if (ret) - { - Throw( FileIOException, "Could not open SDIF file for reading." ); - } - -// -// Read SDIF data. -// - try - { - - // Build up partialsVector. - std::vector< Partial > partialsVector; - SdifFile::markers_type markersVector; - readLorisMatrices( file, partialsVector, markersVector ); - - // Copy partialsVector to partials list. - for (int i = 0; i < partialsVector.size(); ++i) - { - if (partialsVector[i].numBreakpoints() > 0) - { - partials.push_back( partialsVector[i] ); - } - } - - // Copy markersVector to markers list. - for (int i = 0; i < markersVector.size(); ++i) - { - markers.push_back( markersVector[i] ); - } - } - catch ( Exception & ex ) - { - partials.clear(); - markers.clear(); - ex.append(" Failed to read SDIF file."); - SDIF_CloseRead(file); - throw; - } - -// -// Close SDIF input file. -// - SDIF_CloseRead(file); - -// -// Complain if no Partials were imported: -// - if ( partials.size() == 0 ) - { - notifier << "No Partials were imported from " << infilename - << ", no (non-empty) SDIF frames found." << endl; - } - -} - -// -- SDIF writing helpers -- -// --------------------------------------------------------------------------- -// makeSortedBreakpointTimes -// --------------------------------------------------------------------------- -// Collect the times of all breakpoints in the analysis, and sort by time. -// Sorted breakpoints are used in finding frame start times in SDIF writing. -// -struct BreakpointTime -{ - long index; // index identifying which partial has the breakpoint - double time; // time of the breakpoint -}; - -struct earlier_time -{ - bool operator()( const BreakpointTime & lhs, const BreakpointTime & rhs ) const - { return lhs.time < rhs.time; } -}; - -static void -makeSortedBreakpointTimes( const ConstPartialPtrs & partialsVector, - std::list< BreakpointTime > & allBreakpoints ) -{ - -// Make list of all breakpoint times from all partials. - for (int i = 0; i < partialsVector.size(); i++) - { - for ( Partial::const_iterator it = partialsVector[i]->begin(); - it != partialsVector[i]->end(); - ++it ) - { - BreakpointTime bpt; - bpt.index = i; - bpt.time = it.time(); - allBreakpoints.push_back( bpt ); - } - } - -// Sort list of all breakpoint times. - allBreakpoints.sort( earlier_time() ); -} - -// --------------------------------------------------------------------------- -// getNextFrameTime -// --------------------------------------------------------------------------- -// Get time of next frame. -// This helps make SDIF files with exact timing (7-column 1TRC format). -// This uses the previously sorted allBreakpoints list. -// -// All Breakpoints should be const, but for some reason, gcc (on SGI at -// least) makes trouble converting and comparing iterators and const_iterators. -// -static double getNextFrameTime( const double frameTime, - std::list< BreakpointTime > & allBreakpoints, - std::list< BreakpointTime >::iterator & bpTimeIter) -{ -// -// Build up vector of partials that have a breakpoint in this frame, update the vector -// as we increase the frame duration. Return when a partial gets a second breakpoint. -// -// This vector is only used locally. We search this vector of indices to determine -// whether or not a Partial has already contributed a Breakpoint to the current -// frame. -// - double nextFrameTime = frameTime; - std::vector< long > partialsWithBreakpointsInFrame; - - // const std::list< BreakpointTime >::iterator & first = bpTimeIter; - - // invariant: - // Breakpoints in allBreakpoints before the position - // of bpTimeIter have be added to a SDIF frame, either - // the current one or an earlier one. If it is not - // equal to bpTimeIter, then all Breakpoints between - // those two positions have the same time. - std::list< BreakpointTime >::iterator it = bpTimeIter; - while ( it != allBreakpoints.end() && - ( std::find( partialsWithBreakpointsInFrame.begin(), - partialsWithBreakpointsInFrame.end(), - it->index ) == - partialsWithBreakpointsInFrame.end() ) ) - { - // Add breakpoint to list of potential breakpoints for frame, - // then iterate to soonest breakpoint on any partial. The final decision - // to add this breakpoint to the frame is made below, if bpTimeIter is - // updated. - partialsWithBreakpointsInFrame.push_back( it->index ); - - - // If the new breakpoint is at a new time, it could potentially be the - // first breakpoint in the next frame. If there are several breakpoints at - // the exact same time (could happen if these envelopes came from a spc - // file or from resampled envelopes), always start the frame at the first - // of these. Set bpTimeIter if this is a good start of a new frame. - // - // Don't want to increment bpTimeIter until we are certain that all - // coincident Breakpoints can be added to the current frame (that is, - // that none of them are from Partials that already have a Breakpoint - // in this frame). - // - // epsilon controls how close together in time two breakpoints can be. - // Keep this large enough that double-precision floating point math - // can find a time between two breakpoints close in time. One nanosecond - // ought to be plenty close. - ++it; - const double epsilon = 1e-9; - if ( ( it == allBreakpoints.end() ) || ( (it->time - bpTimeIter->time) > epsilon ) ) - { - bpTimeIter = it; - } - } - - if ( bpTimeIter == allBreakpoints.end() ) - { - // We are at the end of the sound; no "next frame" there, - // set the next frame time to something later than the last - // Breakpoint and the current frame time (the current frame - // might be empty, so have to check both). - nextFrameTime = std::max( (double)allBreakpoints.back().time, frameTime ) + 1; - } - else - { - Assert( bpTimeIter != allBreakpoints.begin() ); - - // Compute the next frame time: - // If possible, round it to the nearest millisecond before - // the first Breakpoint in the next frame, otherwise just - // pick a time between the last Breakpoint in the current - // frame and the first Breakpoint in the next. - std::list< BreakpointTime >::iterator prev = bpTimeIter; - --prev; - - // prev and bpTimeIter cannot have the same time, because - // if there are several Breakpoints at the same time, bpTimeIter - // will be the first of them in the list: - Assert( bpTimeIter->time > prev->time ); - - // This seems to be sensitive to floating point error, - // probably because times are stored in 32 bit floats. - // We need the error to round toward the later time. - // - // Note: times are no longer stored in 32 bit floats, - // why is this still so flakey? - nextFrameTime = bpTimeIter->time - ( 0.5 * ( bpTimeIter->time - prev->time ) ); - /* - notifier << "next frame time " << nextFrameTime << endl; - notifier << " bp time " << bpTimeIter->time << endl; - notifier << " prev time " << prev->time << endl; - notifier << " diff = " << bpTimeIter->time - prev->time << endl; - */ - Assert( bpTimeIter->time >= nextFrameTime ); - Assert( nextFrameTime > prev->time ); - - // Try to make frame times whole milliseconds. - // MUST use 32-bit floats for time, or else floating - // point rounding errors cause us to drop breakpoints! - double nextFramePrevRnd = 0.001 * std::floor( 1000. * nextFrameTime ); - if ( ( nextFramePrevRnd < nextFrameTime ) && ( nextFramePrevRnd > prev->time ) ) - { - nextFrameTime = nextFramePrevRnd; - } - else - { - // Try tenth-milliseconds, otherwise give up. - nextFramePrevRnd = 0.0001 * std::floor( 10000. * nextFrameTime ); - if ( ( nextFramePrevRnd < nextFrameTime ) && ( nextFramePrevRnd > prev->time ) ) - { - nextFrameTime = nextFramePrevRnd; - } - } - } - - // notifier << " returning next frame time " << nextFrameTime << endl; - -#if Debug_Loris - if ( ! ( nextFrameTime > frameTime ) ) - { - if ( bpTimeIter != allBreakpoints.end() ) - { - std::cout << bpTimeIter->time << std::endl; - } - else - { - std::cout << "end" << std::endl; - } - // std::cout << first->time << ", index " << first->index << std::endl; - std::cout << nextFrameTime << std::endl; - std::cout << frameTime << std::endl; - std::cout << partialsWithBreakpointsInFrame.size() << std::endl; - } - Assert( nextFrameTime > frameTime ); -#endif - return nextFrameTime; -} - - -// --------------------------------------------------------------------------- -// indexPartials -// --------------------------------------------------------------------------- -// Make a vector of partial pointers. -// The vector index will be the sdif 1TRC index for the partial. -// -static void -indexPartials( const PartialList & partials, ConstPartialPtrs & partialsVector ) -{ - for ( PartialList::const_iterator it = partials.begin(); it != partials.end(); ++it ) - { - if ( it->size() != 0 ) - { - partialsVector.push_back( (Partial *)&(*it) ); //@@@ Kluge Here (Partial *) - // partialsVector.push_back( &(*it) ); - } - } -} - - -// --------------------------------------------------------------------------- -// collectActiveIndices -// --------------------------------------------------------------------------- -// Collect all partials active in a particular frame. -// -// Return true if frameTime is beyond end of all the partials. -// Don't need to return this, can just check frame time against -// the time of the last BreakpointTime in the allBreakpoints vector. -// -static void -collectActiveIndices( const ConstPartialPtrs & partialsVector, - const bool enhanced, - const double frameTime, - const double nextFrameTime, - std::vector< int > & activeIndices ) -{ -#if 1 //Debug_Loris - if ( ! ( nextFrameTime > frameTime ) ) - { - std::cout << nextFrameTime << " <= " << frameTime << std:: endl; - //std::cout << "amp 128 : " << partialsVector[128]->amplitudeAt( frameTime ) << std::endl; - - } -#endif - Assert( nextFrameTime > frameTime ); - - for ( int i = 0; i < partialsVector.size(); i++ ) - { - Assert( partialsVector[ i ] != 0 ); - - const Partial & mightBeActive = *( partialsVector[ i ] ); - - // Is there a breakpoint within the frame? - // Skip the partial if there is no breakpoint and either: - // (1) we are writing enhanced format, - // or (2) the partial has zero amplitude. - // - // Include this Partial if: - // (1) it has a Breakpoint in the frame, or - // (2A) we are not writing enhanced data, and - // (2B) the Partial has non-zero amplitude at the time of - // this frame. - // - Partial::const_iterator it = mightBeActive.findAfter( frameTime ); - if ( it != mightBeActive.end() ) - { -#if Debug_Loris - // DEBUGGING - // if this one is in this frame, then - // the one before it had better be in the previous frame! - if ( ( it != mightBeActive.begin() ) && ( it.time() < nextFrameTime ) ) - { - Partial::const_iterator prev = it; - --prev; - Assert( prev.time() < frameTime ); - } - Assert( it != mightBeActive.end() ); -#endif - - // mightBeActive is active in this frame if the Breakpoint - // at it is earlier than the next frame time. - // - // 1TRC (non-enhanced) contains data for every non-silent - // active Partial at the time of the frame. - if ( ( it.time() < nextFrameTime ) || - ( !enhanced && mightBeActive.amplitudeAt( frameTime ) != 0.0 ) ) - { - activeIndices.push_back( i ); - } - } - - } -} - -// --------------------------------------------------------------------------- -// writeEnvelopeLabels -// --------------------------------------------------------------------------- -// -static void -writeEnvelopeLabels( FILE * out, const ConstPartialPtrs & partialsVector ) -{ -// -// Write Loris labels to SDIF file in a RBEL matrix. -// This precedes the 1TRC data in the file. -// Let exceptions propagate. -// - - int streamID = 2; // stream id different from envelope's stream id - double frameTime = 0.0; - -// -// Allocate RBEL matrix data. -// - int cols = 2; - sdif_float64 *data = new sdif_float64[ partialsVector.size() * cols ]; - -// -// For each partial index, specify the partial label. -// - sdif_float64 *dp = data; - int anyLabel = false; - for (int i = 0; i < partialsVector.size(); i++) - { - int labl = partialsVector[i]->label(); - anyLabel |= (labl != 0); - *dp++ = i; // column 1: index - *dp++ = labl; // column 2: label - } - -// -// Write out matrix data, if there were any labels. -// - if (anyLabel) - { - // Write the frame header. - SDIF_FrameHeader fh; - SDIF_Copy4Bytes(fh.frameType, lorisLabelsSignature); - fh.size = - // size of remaining frame header - sizeof(sdif_float64) + 2 * sizeof(sdif_int32) - // size of matrix header - + sizeof(SDIF_MatrixHeader) - // size of matrix data plus any padding - + 8 * ((partialsVector.size() * cols * sizeof(sdif_float64) + 7) / 8); - fh.time = frameTime; - fh.streamID = streamID; - fh.matrixCount = 1; - SDIFresult ret = SDIF_WriteFrameHeader(&fh, out); - - // Write the matrix header. - SDIF_MatrixHeader mh; - SDIF_Copy4Bytes(mh.matrixType, lorisLabelsSignature); - mh.matrixDataType = SDIF_FLOAT64; - mh.rowCount = partialsVector.size(); - mh.columnCount = cols; - ret = SDIF_WriteMatrixHeader(&mh, out); - - // Write the matrix data, and any necessary padding. - ret = SDIF_WriteMatrixData(out, &mh, data); - } - -// -// Free RBEL matrix space. -// - delete [] data; -} - -// --------------------------------------------------------------------------- -// writeMarkers -// --------------------------------------------------------------------------- -// -static void -writeMarkers( FILE * out, const SdifFile::markers_type &markers ) -{ -// -// Write Loris markers to SDIF file in a RBEM frame. -// This precedes the envelope data in the file. -// Let exceptions propagate. -// - -// -// Exit if there are no markers. -// - if ( markers.empty() ) - { - return; - } - - int streamID = 2; // stream id different from envelope's stream id - double frameTime = 0.0; - -// -// We will need two matrices: one numeric (marker times) matrix data and character (marker names) matrix. -// - std::vector markerTimes; - std::string markerNames; - -// -// Get matrix data from each marker. -// - for (int marker = 0; marker < markers.size(); marker++) - { - markerTimes.push_back( markers[marker].time() ); - markerNames += markers[marker].name() + '\0'; - } - -// -// Write out frame with two marker matrices. -// - // Write the frame header. - int cols = 1; - { - SDIF_FrameHeader fh; - SDIF_Copy4Bytes( fh.frameType, lorisMarkersSignature ); - fh.size = - // size of remaining frame header - sizeof( sdif_float64 ) + 2 * sizeof( sdif_int32 ) - // size of matrix headers - + 2 * sizeof( SDIF_MatrixHeader ) - // size of numeric (time) matrix data - + markerTimes.size() * sizeof( sdif_float64 ) - // size of marker names data plus padding - + 8 * ( ( markerNames.size() + 7 ) / 8 ); - fh.time = frameTime; - fh.streamID = streamID; - fh.matrixCount = 2; - // SDIFresult ret = return value never checked! - SDIF_WriteFrameHeader(&fh, out); - } - - // Write the numeric (marker times) matrix. - { - // Write the numeric (time) matrix header. - SDIF_MatrixHeader mh; - SDIF_Copy4Bytes( mh.matrixType, lorisMarkersSignature ); - mh.matrixDataType = SDIF_FLOAT64; - mh.rowCount = markerTimes.size(); - mh.columnCount = cols; - SDIFresult ret = SDIF_WriteMatrixHeader( &mh, out ); - - // Write the numeric (time) matrix data, and any necessary padding. - ret = SDIF_WriteMatrixData( out, &mh, &markerTimes[0] ); - } - - // Write the string (marker names) matrix. - { - // Write the string (names) matrix header. - SDIF_MatrixHeader mh; - SDIF_Copy4Bytes( mh.matrixType, lorisMarkersSignature ); - mh.matrixDataType = SDIF_UTF8; - mh.rowCount = markerNames.size(); - mh.columnCount = cols; - SDIFresult ret = SDIF_WriteMatrixHeader( &mh, out ); - - // Write the string (names) matrix data, and any necessary padding. - ret = SDIF_WriteMatrixData( out, &mh, &markerNames[0] ); - } -} - - -// --------------------------------------------------------------------------- -// assembleMatrixData -// --------------------------------------------------------------------------- -// The activeIndices vector contains indices for partials that have data at this time. -// Assemble SDIF matrix data for these partials. -// -static void -assembleMatrixData( sdif_float64 *data, const bool enhanced, - const ConstPartialPtrs & partialsVector, - const std::vector< int > & activeIndices, - const double frameTime ) -{ - // The array matrix data is row-major order at "data". - sdif_float64 *rowDataPtr = data; - - for ( int i = 0; i < activeIndices.size(); i++ ) - { - - int index = activeIndices[ i ]; - const Partial * par = partialsVector[ index ]; - - // For enhanced format we use exact timing; the activeIndices only includes - // partials that have breakpoints in this frame. - // For sine-only format we resample at frame times, for enhanced, use - // the Breakpoints themselves. - Assert( par->endTime() >= frameTime ); - double tim = frameTime; - Breakpoint params; - if ( enhanced ) - { - Partial::const_iterator pos = par->findAfter( frameTime ); - tim = pos.time(); - params = pos.breakpoint(); - } - else - { - params = par->parametersAt( frameTime ); - } - - // Must have phase between 0 and 2*Pi. - double phas = params.phase(); - if (phas < 0) - { - phas += 2. * Pi; - } - - // Fill in values for this row of matrix data. - *rowDataPtr++ = index; // first row of matrix (standard) - *rowDataPtr++ = params.frequency(); // second row of matrix (standard) - *rowDataPtr++ = params.amplitude(); // third row of matrix (standard) - *rowDataPtr++ = phas; // fourth row of matrix (standard) - if (enhanced) - { - *rowDataPtr++ = params.bandwidth(); // fifth row of matrix (loris) - *rowDataPtr++ = tim - frameTime; // sixth row of matrix (loris) - } - } -} - - -// --------------------------------------------------------------------------- -// writeEnvelopeData -// --------------------------------------------------------------------------- -// -static void -writeEnvelopeData( FILE * out, - const ConstPartialPtrs & partialsVector, - const bool enhanced ) -{ -// -// Export SDIF file from Loris data. -// Let exceptions propagate. -// - - int streamID = 1; // one stream id for all SDIF frames - -// -// Make a sorted list of all breakpoints in all partials, and initialize the list iterater. -// This stuff does nothing if we are writing 5-column 1TRC format. -// - std::list< BreakpointTime > allBreakpoints; - makeSortedBreakpointTimes( partialsVector, allBreakpoints ); - std::list< BreakpointTime >::iterator bpTimeIter = allBreakpoints.begin(); - -#if Debug_Loris - const std::list< BreakpointTime >::size_type DEBUG_allBreakpointsSize = allBreakpoints.size(); - std::list< BreakpointTime >::size_type DEBUG_cumNumTracks = 0; -#endif - -// -// Output Loris envelope data in SDIF frame format. -// First frame starts at millisecond of first breakpoint. -// - double nextFrameTime = allBreakpoints.front().time; - if ( 1000. * nextFrameTime - int( 1000. * nextFrameTime ) != 0. ) - { - // HEY! Looks like this could give negative frame times, - // is that allowed? - nextFrameTime = std::floor( 1000. * nextFrameTime - .001 ) / 1000.0; - } - - do - { - -// -// Go to next frame. -// - double frameTime = nextFrameTime; - nextFrameTime = getNextFrameTime( frameTime, allBreakpoints, bpTimeIter ); - -// -// Make a vector of partial indices that includes all partials active at this time. -// - std::vector< int > activeIndices; - collectActiveIndices( partialsVector, enhanced, frameTime, - nextFrameTime, activeIndices ); - -// -// Write frame header, matrix header, and matrix data. -// We always have one matrix per frame. -// The matrix size depends on the number of partials active at this time. -// - int numTracks = activeIndices.size(); - -#if Debug_Loris - DEBUG_cumNumTracks += numTracks; -#endif - - if ( numTracks > 0 ) // could activeIndices ever be empty? - { - - // Allocate matrix data. - int cols = ( enhanced ? lorisRowEnhancedElements : lorisRowSineOnlyElements ); - - // I think this will go a lot faster if we aren't doing so much - // dynamic memory allocation for each frame. if I use a vector, - // then we only need to allocate more memory when a frame has more - // columns than any previous frame. Construct the vector once, - // resize it for each frame, and clear it when done (doesn't - // deallocate memory). - // sdif_float64 *data = new sdif_float64[numTracks * cols]; - static std::vector< sdif_float64 > dataVector; - dataVector.resize( numTracks * cols ); - - // Fill in matrix data. - sdif_float64 *data = &dataVector[ 0 ]; - assembleMatrixData( data, enhanced, partialsVector, activeIndices, frameTime ); - - // Write the frame header. - SDIF_FrameHeader fh; - SDIF_Copy4Bytes( fh.frameType, enhanced ? lorisEnhancedSignature : lorisSineOnlySignature ); - fh.size = - // size of remaining frame header - sizeof(sdif_float64) + 2 * sizeof(sdif_int32) - // size of matrix header - + sizeof(SDIF_MatrixHeader) - // size of matrix data plus any padding - + 8*((numTracks * cols * sizeof(sdif_int32) + 7)/8); - fh.streamID = streamID; - fh.time = frameTime; - fh.matrixCount = 1; - SDIFresult ret = SDIF_WriteFrameHeader(&fh, out); - - // Write the matrix header. - SDIF_MatrixHeader mh; - SDIF_Copy4Bytes( mh.matrixType, enhanced ? lorisEnhancedSignature : lorisSineOnlySignature ); - mh.matrixDataType = SDIF_FLOAT64; - mh.rowCount = numTracks; - mh.columnCount = cols; - ret = SDIF_WriteMatrixHeader( &mh, out ); - - // Write the matrix data, and any necessary padding. - ret = SDIF_WriteMatrixData( out, &mh, data ); - - // Free matrix space. - // delete [] data; - // Instead of deallocating, just clear the static - // vector, setting its logical size to zero. - dataVector.clear(); - } - } - while ( nextFrameTime < allBreakpoints.back().time ); - -#if Debug_Loris - std::cout << "SDIF export found " << DEBUG_allBreakpointsSize << " Breakpoints" << std::endl; - std::cout << "and exported " << DEBUG_cumNumTracks << std::endl; -#endif -} - -// --------------------------------------------------------------------------- -// Export -// --------------------------------------------------------------------------- -// Export SDIF file. -// -static void export_sdif( const std::string & filename, - const SdifFile::partials_type & partials, - const SdifFile::markers_type &markers, const bool enhanced ) -{ -// -// Initialize CNMAT SDIF routines. -// - SDIFresult ret = SDIF_Init(); - if (ret) - { - Throw( FileIOException, "Could not initialize SDIF routines." ); - } -// -// Open SDIF file for writing. -// - FILE *out; - ret = SDIF_OpenWrite(filename.c_str(), &out); - if (ret) - { - Throw( FileIOException, "Could not open SDIF file for writing: " + filename ); - } - - // We are no longer defining frame types. - - // // Define RBEP matrix and frame type for enhanced partials. - // if (enhanced) - // { - // SdifMatrixTypeT *parsMatrixType = SdifCreateMatrixType(lorisEnhancedSignature,NULL); - // SdifMatrixTypeInsertTailColumnDef(parsMatrixType,"Index"); - // SdifMatrixTypeInsertTailColumnDef(parsMatrixType,"Frequency"); - // SdifMatrixTypeInsertTailColumnDef(parsMatrixType,"Amplitude"); - // SdifMatrixTypeInsertTailColumnDef(parsMatrixType,"Phase"); - // SdifMatrixTypeInsertTailColumnDef(parsMatrixType,"Noise"); - // SdifMatrixTypeInsertTailColumnDef(parsMatrixType,"TimeOffset"); - // SdifPutMatrixType(out->MatrixTypesTable, parsMatrixType);// - // - // SdifFrameTypeT *parsFrameType = SdifCreateFrameType(lorisEnhancedSignature,NULL); - // SdifFrameTypePutComponent(parsFrameType, lorisEnhancedSignature, "RABWE_Partials"); - // SdifPutFrameType(out->FrameTypesTable, parsFrameType); - // } - // - // // Define RBEL matrix and frame type for labels. - // SdifMatrixTypeT *labelsMatrixType = SdifCreateMatrixType(lorisLabelsSignature,NULL); - // SdifMatrixTypeInsertTailColumnDef(labelsMatrixType,"Index"); - // SdifMatrixTypeInsertTailColumnDef(labelsMatrixType,"Label"); - // SdifPutMatrixType(out->MatrixTypesTable, labelsMatrixType); - // - // SdifFrameTypeT *labelsFrameType = SdifCreateFrameType(lorisLabelsSignature,NULL); - // SdifFrameTypePutComponent(labelsFrameType, lorisLabelsSignature, "RABWE_Labels"); - // SdifPutFrameType(out->FrameTypesTable, labelsFrameType); - // - // // Write file header information - // SdifFWriteGeneralHeader( out ); - // - // // Write ASCII header information - // SdifFWriteAllASCIIChunks( out ); - -// -// Write SDIF data. -// - try - { - // Make vector of pointers to partials. - ConstPartialPtrs partialsVector; - indexPartials( partials, partialsVector ); - - // Write labels. - writeEnvelopeLabels( out, partialsVector ); - - // Write markers. - writeMarkers(out, markers); - - // Write partials to SDIF file. - writeEnvelopeData( out, partialsVector, enhanced ); - } - catch ( Exception & ex ) - { - ex.append( " Failed to write SDIF file." ); - SDIF_CloseWrite( out ); - throw; - } - -// -// Close SDIF input file. -// - SDIF_CloseWrite( out ); -} - -// --------------------------------------------------------------------------- -// Export -// --------------------------------------------------------------------------- -// Legacy static export member. -// -void -SdifFile::Export( const std::string & filename, const PartialList & partials, - const bool enhanced ) -{ - SdifFile fout( partials.begin(), partials.end() ); - if ( enhanced ) - fout.write( filename ); - else - fout.write1TRC( filename ); -} - - -} // end of namespace Loris - - diff --git a/loris_library/Source/src/SdifFile.h b/loris_library/Source/src/SdifFile.h deleted file mode 100644 index 8408c28..0000000 --- a/loris_library/Source/src/SdifFile.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SdifFile.h - * - * Definition of SdifFile class for Partial import and export in Loris. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Marker.h" -#include "Partial.h" -#include "PartialList.h" - -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class SdifFile -// -//! Class SdifFile represents reassigned bandwidth-enhanced Partial -//! data in a SDIF-format data file. Construction of an SdifFile -//! from a stream or filename automatically imports the Partial -//! data. -//! -//! Loris stores partials in SDIF RBEP and RBEL frames. The RBEP and RBEL -//! frame and matrix definitions are included in the SDIF file's header. -//! Each RBEP frame contains one RBEP matrix, and each row in a RBEP matrix -//! describes one breakpoint in a Loris partial. The data in RBEP matrices -//! are SDIF 32-bit floats. -//! -//! The six columns in an RBEP matrix are: partialIndex, frequency, -//! amplitude, phase, noise, timeOffset. The partialIndex uniquely -//! identifies a partial. When Loris exports SDIF data, each partial is -//! assigned a unique partialIndex. The frequency (Hz), amplitude (0..1), -//! phase (radians), and noise (bandwidth) are encoded the same as Loris -//! breakpoints. The timeOffset is an offset from the RBEP frame time, -//! specifying the exact time of the breakpoint. Loris always specifies -//! positive timeOffsets, and the breakpoint's exact time is always be -//! earlier than the next RBEP frame's time. -//! -//! Since reassigned bandwidth-enhanced partial breakpoints are -//! non-uniformly spaced in time, the RBEP frame times are also -//! non-uniformly spaced. Each RBEP frame will contain at most one -//! breakpoint for any given partial. A partial may extend over a RBEP frame -//! and have no breakpoint specified by the RBEP frame, as happens when one -//! active partial has a lower temporal density of breakpoints than other -//! active partials. -//! -//! If partials have nonzero labels in Loris, then a RBEL frame describing -//! the labeling of the partials will precede the first RBEP frame in the -//! SDIF file. The RBEL frame contains a single, two-column RBEL matrix The -//! first column is the partialIndex, and the second column specifies the -//! label for the partial. -//! -//! If markers are associated with the partials in Loris, then a RBEM frame -//! describing the markers will precede the first RBEP frame in the SDIF -//! file. The RBEM frame contains two single-column RBEM matrices. The -//! first matrix contains 32-bit floats indicating the time (in seconds) -//! for each marker. The second matrix contains UTF-8 data, the names of -//! each of the markers separated by the ASCII character 0. -//! -//! In addition to RBEP frames, Loris can also read and write SDIF 1TRC -//! frames (refer to IRCAM's SDIF web site, www.ircam.fr/sdif/, for -//! definitions of standard SDIF description types). Since 1TRC frames do -//! not represent bandwidth-enhancement or the exact timing of Loris -//! breakpoints, their use is not recommended. 1TRC capabilities are -//! provided in Loris to allow interchange with programs that are unable to -//! interpret RBEP frames. -// -class SdifFile -{ -// -- public interface -- -public: - -// -- types -- - - //! The type of marker storage in an SdifFile. - typedef std::vector< Marker > markers_type; - - //! The type of the Partial storage in an AiffFile. - typedef PartialList partials_type; - -// -- construction -- - - //! Initialize an instance of SdifFile by importing Partial data from - //! the file having the specified filename or path. - explicit SdifFile( const std::string & filename ); - - //! Initialize an instance of SdifFile with copies of the Partials - //! on the specified half-open (STL-style) range. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. -#if !defined(NO_TEMPLATE_MEMBERS) - template - SdifFile( Iter begin_partials, Iter end_partials ); -#else - SdifFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ); -#endif - - //! Initialize an empty instance of SdifFile having no Partials. - SdifFile( void ); - - // copy, assign, and delete are compiler-generated - -// -- access -- - - //! Return a reference to the Markers (see Marker.h) - //! for this SdifFile. - markers_type & markers( void ); - - //! Return a reference to the Markers (see Marker.h) - //! for this SdifFile. - const markers_type & markers( void ) const; - - //! Return a reference to the bandwidth-enhanced - //! Partials represented by this SdifFile. - partials_type & partials( void ); - - //! Return a reference to the bandwidth-enhanced - //! Partials represented by this SdifFile. - const partials_type & partials( void ) const; -// -- mutation -- - - //! Add a copy of the specified Partial to this SdifFile. - void addPartial( const Loris::Partial & p ); - - //! Add a copy of each Partial on the specified half-open (STL-style) - //! range to this SdifFile. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. -#if !defined(NO_TEMPLATE_MEMBERS) - template - void addPartials( Iter begin_partials, Iter end_partials ); -#else - void addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ); -#endif - -// -- export -- - - //! Export the envelope Partials represented by this SdifFile to - //! the file having the specified filename or path. - void write( const std::string & path ); - - //! Export the envelope Partials represented by this SdifFile to - //! the file having the specified filename or path in the 1TRC - //! format, resampled, and without phase or bandwidth information. - void write1TRC( const std::string & path ); - -// -- legacy export -- - - //! Export the Partials in the specified PartialList to a SDIF file having - //! the specified file name or path. If enhanced is true (the default), - //! reassigned bandwidth-enhanced Partial data are exported in the - //! six-column RBEP format. Otherwise, the Partial data is exported as - //! resampled sinusoidal analysis data in the 1TRC format. - //! Provided for backwards compatability. - //! - //! \deprecated This function is included only for legacy support - //! and may be removed at any time. - static void Export( const std::string & filename, - const PartialList & plist, - const bool enhanced = true ); - -private: -// -- implementation -- - partials_type partials_; // Partials to store in SDIF format - markers_type markers_; // AIFF Markers - -}; // end of class SdifFile - -// -- template members -- - -// --------------------------------------------------------------------------- -// constructor from Partial range -// --------------------------------------------------------------------------- -// Initialize an instance of SdifFile with copies of the Partials -// on the specified half-open (STL-style) range. -// -// If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -// only PartialList::const_iterator arguments. -// -#if !defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -SdifFile::SdifFile( Iter begin_partials, Iter end_partials ) -#else -SdifFile::SdifFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ) -#endif -{ - addPartials( begin_partials, end_partials ); -} - -// --------------------------------------------------------------------------- -// addPartials -// --------------------------------------------------------------------------- -// Add a copy of each Partial on the specified half-open (STL-style) -// range to this SdifFile. -// -// If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -// only PartialList::const_iterator arguments. -// -#if !defined(NO_TEMPLATE_MEMBERS) -template -void SdifFile::addPartials( Iter begin_partials, Iter end_partials ) -#else -void SdifFile::addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ) -#endif -{ - partials_.insert( partials_.end(), begin_partials, end_partials ); -} - -} // end of namespace Loris - diff --git a/loris_library/Source/src/Sieve.cpp b/loris_library/Source/src/Sieve.cpp deleted file mode 100644 index dc25992..0000000 --- a/loris_library/Source/src/Sieve.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Sieve.C - * - * Implementation of class Sieve. - * - * Lippold Haken, 20 Jan 2001 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Sieve.h" -#include "Breakpoint.h" -#include "LorisExceptions.h" -#include "Notifier.h" -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" - -#include - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// Sieve constructor -// --------------------------------------------------------------------------- -//! Construct a new Sieve using the specified partial fade -//! time. If unspecified, the default fade time (same as the -//! default fade time for the Distiller) is used. -//! -//! \param partialFadeTime is the extra time (in seconds) -//! added to each end of a Partial to accomodate -//! the fade to and from zero amplitude. Fade time -//! must be non-negative. A default value is used -//! if unspecified. -//! \throw InvalidArgument if partialFadeTime is negative. -// -Sieve::Sieve( double partialFadeTime ) : - _fadeTime( partialFadeTime ) -{ - if ( _fadeTime < 0.0 ) - { - Throw( InvalidArgument, "the Partial fade time must be non-negative" ); - } -} - -// Definition of a comparitor for sorting a collection of pointers -// to Partials by label (increasing) and duration (decreasing), so -// that Partial ptrs are arranged by label, with the lowest labels -// first, and then with the longest Partials having each label -// before the shorter ones. -struct SortPartialPtrs : - public std::binary_function< const Partial *, const Partial *, bool > -{ - bool operator()( const Partial * lhs, const Partial * rhs ) const - { - return ( lhs->label() != rhs->label() ) ? - ( lhs->label() < rhs->label() ) : - ( lhs->duration() > rhs->duration() ); - } -}; - -// Definition of predicate for finding the end of a Patial * -// range having a common label. -struct PartialPtrLabelNE : - public std::unary_function< const Partial *, bool > -{ - int label; - PartialPtrLabelNE( int l ) : label(l) {} - - bool operator()( const Partial * p ) const - { return p->label() != label; } -}; - - -// --------------------------------------------------------------------------- -// find_overlapping (template function) -// --------------------------------------------------------------------------- -// Iterate over a range of Partials (presumably) with same labeling. -// The range is specified by iterators over a collection of pointers -// to Partials (not Partials themselves). Return the first position -// in the specified range corresponding to a Partial that overlaps -// (in time) the specified Partial, p, or the end of the range if -// no Partials in the range overlap. -// -// Overlap is defined by the minimum time gap between Partials -// (minGapTime), so Partials that have less then minGapTime -// between them are considered overlapping. -// -template // Iter is the position of a Partial * -Iter -find_overlapping( Partial & p, double minGapTime, Iter start, Iter end) -{ - for ( Iter it = start; it != end; ++it ) - { - // skip if other partial is already sifted out. - if ( (*it)->label() == 0 ) - continue; - - // skip the source Partial: - // (identity test: compare addresses) - // (this is a sanity check, should not happen since - // src should be at position end) - Assert( (*it) != &p ); - - // test for overlap: - if ( p.startTime() < (*it)->endTime() + minGapTime && - p.endTime() + minGapTime > (*it)->startTime() ) - { - // Does the overlapping Partial have longer duration? - // (this should never be true, since the Partials - // are sorted by duration) - Assert( p.duration() <= (*it)->duration() ); - -#if Debug_Loris - debugger << "Partial starting " << p.startTime() << ", " - << p.begin().breakpoint().frequency() << " ending " - << p.endTime() << ", " << (--p.end()).breakpoint().frequency() - << " zapped by overlapping Partial starting " - << (*it)->startTime() << ", " << (*it)->begin().breakpoint().frequency() - << " ending " << (*it)->endTime() << ", " - << (--(*it)->end()).breakpoint().frequency() << endl; -#endif - return it; - } - } - - // no overlapping Partial found: - return end; -} - -// --------------------------------------------------------------------------- -// sift_ptrs (private helper) -// --------------------------------------------------------------------------- -//! Sift labeled Partials. If any two Partials having the same (non-zero) -//! label overlap in time (where overlap includes the fade time at both -//! ends of each Partial), then set the label of the Partial having the -//! shorter duration to zero. Sifting is performed on a collection of -//! pointers to Partials so that the it can be performed without changing -//! the order of the Partials in the sequence. -//! -//! \param ptrs is a collection of pointers to the Partials in the -//! sequence to be sifted. -void -Sieve::sift_ptrs( PartialPtrs & ptrs ) -{ - // the minimum gap between Partials is twice the - // specified fadeTime: - double minGapTime = _fadeTime * 2.; - - // sort the collection of pointers to Partials: - // (sort is by increasing label, then - // decreasing duration) - std::sort( ptrs.begin(), ptrs.end(), SortPartialPtrs() ); - - PartialPtrs::iterator sift_begin = ptrs.begin(); - PartialPtrs::iterator sift_end = ptrs.end(); - - int zapped = 0; - - // iterate over labels and sift each one: - PartialPtrs::iterator lowerbound = sift_begin; - while ( lowerbound != sift_end ) - { - int label = (*lowerbound)->label(); - - // first the first element in l after sieve_begin - // having a label not equal to 'label': - PartialPtrs::iterator upperbound = - std::find_if( lowerbound, sift_end, PartialPtrLabelNE(label) ); - -#ifdef Debug_Loris - // don't want to compute this iterator distance unless debugging: - debugger << "sifting Partials labeled " << label << endl; - debugger << "Sieve found " << std::distance( lowerbound, upperbound ) << - " Partials labeled " << label << endl; -#endif - // sift all partials with this label, unless the - // label is 0: - if ( label != 0 ) - { - PartialPtrs::iterator it; - for ( it = lowerbound; it != upperbound; ++it ) - { - // find_overlapping only needs to consider Partials on the - // half-open range [lowerbound, it), because all - // Partials after it are shorter, thanks to the - // sorting of the sift_set: - if( it != find_overlapping( **it, minGapTime, lowerbound, it ) ) - { - (*it)->setLabel(0); - ++zapped; - } - } - } - - // advance Partial set iterator: - lowerbound = upperbound; - } - -#ifdef Debug_Loris - debugger << "Sifted out (relabeled) " << zapped << " of " << ptrs.size() << "." << endl; -#endif -} - -} // end of namespace Loris - diff --git a/loris_library/Source/src/Sieve.h b/loris_library/Source/src/Sieve.h deleted file mode 100644 index aff3f16..0000000 --- a/loris_library/Source/src/Sieve.h +++ /dev/null @@ -1,269 +0,0 @@ -#ifndef INCLUDE_SIEVE_H -#define INCLUDE_SIEVE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Sieve.h - * - * Definition of class Sieve. - * - * Lippold Haken, 20 Jan 2001 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Distiller.h" // for default fade time and silent time - -#if defined(NO_TEMPLATE_MEMBERS) -#include "PartialList.h" -#endif - -#include "PartialPtrs.h" - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Sieve -// -//! A Sieve eliminating temporal overlap among Partials. -//! -//! Class Sieve represents an algorithm for identifying channelized (see also -//! Channelizer) Partials that overlap in time, and selecting the longer -//! one to represent the channel. The identification of overlap includes -//! the time needed for Partials to fade to and from zero amplitude in -//! synthesis (see also Synthesizer) or distillation. (see also Distiller) -//! -//! In some cases, the energy redistribution effected by the distiller -//! (see also Distiller) is undesirable. In such cases, the partials can be -//! sifted before distillation. The sifting process in Loris identifies -//! all the partials that would be rejected (and converted to noise -//! energy) by the distiller and assigns them a label of 0. These sifted -//! partials can then be identified and treated sepearately or removed -//! altogether, or they can be passed through the distiller unlabeled, and -//! crossfaded in the morphing process (see also Morpher). -//! -//! \sa Channelizer, Distiller, Morpher, Synthesizer -// -class Sieve -{ -// -- instance variables -- - - double _fadeTime; //! extra time (in seconds) added to each end of - //! a Partial when determining overlap, to accomodate - //! the fade to and from zero amplitude. - -// -- public interface -- -public: - -// -- global defaults and constants -- - - enum - { - - //! Default time in milliseconds over which Partials joined by - //! distillation fade to and from zero amplitude. Divide by - //! 1000 to use as a member function parameter. This parameter - //! should be the same in Distiller, Sieve, and Collator. - DefaultFadeTimeMs = Distiller::DefaultFadeTimeMs, - - //! Default minimum duration in milliseconds of the silent - //! (zero-amplitude) gap between two Partials joined by - //! distillation. Divide by 1000 to use as a member function - //! parameter. This parameter should be the same in Distiller, - //! Sieve, and Collator. - DefaultSilentTimeMs = Distiller::DefaultSilentTimeMs - }; - -// -- construction -- - - //! Construct a new Sieve using the specified partial fade - //! time. If unspecified, the default fade time (same as the - //! default fade time for the Distiller) is used. - //! - //! \param partialFadeTime is the extra time (in seconds) - //! added to each end of a Partial to accomodate - //! the fade to and from zero amplitude. Fade time - //! must be non-negative. A default value is used - //! if unspecified. - //! \throw InvalidArgument if partialFadeTime is negative. - explicit Sieve( double partialFadeTime = Sieve::DefaultFadeTimeMs/1000.0 ); - - // Use compiler-generated copy, assign, and destroy. - -// -- sifting -- - - //! Sift labeled Partials on the specified half-open (STL-style) - //! range. If any two Partials having same label overlap in time, keep - //! only the longer of the two Partials. Set the label of the shorter - //! duration partial to zero. No Partials are removed from the - //! sequence and the sequence order is unaltered. - //! - //! \param sift_begin is the beginning of the range of Partials to sift - //! \param sift_end is (one-past) the end of the range of Partials to sift - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then sift_begin and - //! sift_end must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void sift( Iter sift_begin, Iter sift_end ); -#else - inline - void sift( PartialList::iterator sift_begin, PartialList::iterator sift_end ); -#endif - - //! Sift labeled Partials in the specified container - //! If any two Partials having same label overlap in time, keep - //! only the longer of the two Partials. Set the label of the shorter - //! duration partial to zero. No Partials are removed from the - //! container and the container order is unaltered. - //! - //! \param partials is the collection of Partials to sift in-place - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials - //! must be a PartialList, otherwise it can be any container type - //! storing Partials that supports at least bidirectional iterators. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Container > - void sift( Container & partials ) -#else - inline - void sift( PartialList & partials ) -#endif - { - sift( partials.begin(), partials.end() ); - } - -// -- static members -- - - //! Static member that constructs an instance and applies - //! it to a sequence of Partials. - //! Construct a Sieve using the specified Partial - //! fade time (in seconds), and use it to sift a - //! sequence of Partials. - //! - //! \param sift_begin is the beginning of the range of Partials to sift - //! \param sift_end is (one-past) the end of the range of Partials to sift - //! \param partialFadeTime is the extra time (in seconds) - //! added to each end of a Partial to accomodate - //! the fade to and from zero amplitude. The Partial fade time - //! must be non-negative. - //! \throw InvalidArgument if partialFadeTime is negative. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - static - void sift( Iter sift_begin, Iter sift_end, - double partialFadeTime ); -#else - static inline - void sift( PartialList::iterator sift_begin, PartialList::iterator sift_end, - double partialFadeTime ); -#endif - -// -- helper -- -private: - - //! Sift labeled Partials. If any two Partials having the same (non-zero) - //! label overlap in time (where overlap includes the fade time at both - //! ends of each Partial), then set the label of the Partial having the - //! shorter duration to zero. Sifting is performed on a collection of - //! pointers to Partials so that the it can be performed without changing - //! the order of the Partials in the sequence. - //! - //! \param ptrs is a collection of pointers to the Partials in the - //! sequence to be sifted. - void sift_ptrs( PartialPtrs & ptrs ); - -}; // end of class Sieve - -// --------------------------------------------------------------------------- -// sift -// --------------------------------------------------------------------------- -//! Sift labeled Partials on the specified half-open (STL-style) -//! range. If any two Partials having same label overlap in time, keep -//! only the longer of the two Partials. Set the label of the shorter -//! duration partial to zero. No Partials are removed from the -//! sequence and the sequence order is unaltered. -//! -//! \param sift_begin is the beginning of the range of Partials to sift -//! \param sift_end is (one-past) the end of the range of Partials to sift -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then sift_begin and -//! sift_end must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Sieve::sift( Iter sift_begin, Iter sift_end ) -#else -inline -void Sieve::sift( PartialList::iterator sift_begin, PartialList::iterator sift_end ) -#endif -{ - PartialPtrs ptrs; - fillPartialPtrs( sift_begin, sift_end, ptrs ); - sift_ptrs( ptrs ); -} - -// --------------------------------------------------------------------------- -// sift (static) -// --------------------------------------------------------------------------- -//! Static member that constructs an instance and applies -//! it to a sequence of Partials. -//! Construct a Sieve using the specified Partial -//! fade time (in seconds), and use it to sift a -//! sequence of Partials. -//! -//! \param sift_begin is the beginning of the range of Partials to sift -//! \param sift_end is (one-past) the end of the range of Partials to sift -//! \param partialFadeTime is the extra time (in seconds) -//! added to each end of a Partial to accomodate -//! the fade to and from zero amplitude. The Partial fade time -//! must be non-negative. -//! \throw InvalidArgument if partialFadeTime is negative. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -void Sieve::sift( Iter sift_begin, Iter sift_end, - double partialFadeTime ) -#else -inline -void Sieve::sift( PartialList::iterator sift_begin, PartialList::iterator sift_end, - double partialFadeTime ) -#endif -{ - Sieve instance( partialFadeTime ); - instance.sift( sift_begin, sift_end ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_SIEVE_H */ diff --git a/loris_library/Source/src/SpcFile.cpp b/loris_library/Source/src/SpcFile.cpp deleted file mode 100644 index 66a7a17..0000000 --- a/loris_library/Source/src/SpcFile.cpp +++ /dev/null @@ -1,1311 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpcFile.C - * - * Implementation of SpcFile class for Partial import and export for - * real-time synthesis in Kyma. - * - * Spc files always represent a number of Partials that is a power of - * two. This is not necessary for purely-sinusoidal files, but might be - * (not clear) for enhanced data to be properly processed in Kyma. - * - * All of this is kind of disgusting right now. This code has evolved - * somewhat randomly, and we are awaiting full support for bandwidth- - * enhanced data in Kyma.. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "SpcFile.h" - -#include "AiffData.h" -#include "Breakpoint.h" -#include "BigEndian.h" -#include "LorisExceptions.h" -#include "Marker.h" -#include "Notifier.h" -#include "PartialUtils.h" - -#include -#include -#include - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - - -// Define this if SpcFiles should always have a number of -// Partials that is a power of two. Cannot decide whether -// or not they should. Lip? -#define PO2 - - -using std::exp; -using std::log; -using std::sqrt; - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// constants, can, or should, these be made variable? -// --------------------------------------------------------------------------- - -// can't we change this? Seems like we could, but -// its part of the size of the magic junk in the -// Sose chunk. -const int LargestLabel = 256; // max number of partials for SPC file - - // 1 Mar 05 - // Found that this cannot actually be 512 for enhanced - // Partials, it crashes with a segmentation fault above 256. - // Unfortunately, whatever is causing the problem is not - // using this constant, but some other hardcoded thing. - // if I change this to 256, then I can still export - // 256 enhanced Partials, but I don't know what to change - // to allow 512! Ugh! - // -kel - - -// this used to be hard coded into Partial, don't know -// whether it is needed to make spc files work. -const double Fade = 0.001; - -// this always has to be 24 bits, 1 channel -const int Bps = 24; -const int Nchans = 1; - - -// --------------------------------------------------------------------------- -// static helper prototypes, defined at bottom -// --------------------------------------------------------------------------- -static void -configureEnvelopeDataCk( SoundDataCk & ck, const SpcFile::partials_type & partials ); - -static void -configureSosMarkerCk( MarkerCk & ck, const std::vector< Marker > & markers ); - -static void -configureSosEnvelopesCk( SosEnvelopesCk & ck ); - -static std::ostream & -writeSosEnvelopesChunk( std::ostream & s, const SosEnvelopesCk & ck ); - -static void -configureExportStruct( const SpcFile::partials_type & partials, double midipitch, - double endApproachTime, int enhanced ); - -static unsigned long getNumSampleFrames( void ); - -const int SpcFile::MinNumPartials = 32; -const double SpcFile::DefaultRate = 44100.; - -// -- construction -- -// --------------------------------------------------------------------------- -// SpcFile constructor from filename -// --------------------------------------------------------------------------- -// Initialize an instance of SpcFile by importing envelope parameter -// streams from the file having the specified filename or path. -// -SpcFile::SpcFile( const std::string & filename ) : - notenum_( 60 ), - rate_( DefaultRate ) -{ - readSpcData( filename ); -} - -// --------------------------------------------------------------------------- -// SpcFile constructor, empty. -// --------------------------------------------------------------------------- -// Initialize an instance of SpcFile having the specified fractional -// MIDI note number, and no Partials (or envelope parameter streams). -// -SpcFile::SpcFile( double midiNoteNum ) : - notenum_( midiNoteNum ), - rate_( DefaultRate ) -{ - growPartials( MinNumPartials ); -} - -// --------------------------------------------------------------------------- -// write -// --------------------------------------------------------------------------- -// Export the phase-correct bandwidth-enhanced envelope parameter -// streams represented by this SpcFile to the file having the specified -// filename or path. -// -// A nonzero endApproachTime indicates that the Partials do not include a -// release or decay, but rather end in a static spectrum corresponding to the -// final Breakpoint values of the partials. The endApproachTime specifies how -// long before the end of the sound the amplitude, frequency, and bandwidth -// values are to be modified to make a gradual transition to the static spectrum. -// -// If the endApproachTime is not specified, it is assumed to be zero, -// corresponding to Partials that decay or release normally. -// -void -SpcFile::write( const std::string & filename, double endApproachTime ) -{ - write( filename, true, endApproachTime ); -} - -// --------------------------------------------------------------------------- -// write -// --------------------------------------------------------------------------- -// Export the pure sinsoidal (omitting phase and bandwidth data) envelope -// parameter streams represented by this SpcFile to the file having the -// specified filename or path. -// -// A nonzero endApproachTime indicates that the Partials do not include a -// release or decay, but rather end in a static spectrum corresponding to the -// final Breakpoint values of the partials. The endApproachTime specifies how -// long before the end of the sound the amplitude, frequency, and bandwidth -// values are to be modified to make a gradual transition to the static spectrum. -// -// If the endApproachTime is not specified, it is assumed to be zero, -// corresponding to Partials that decay or release normally. -// -void -SpcFile::writeSinusoidal( const std::string & filename, double endApproachTime ) -{ - write( filename, false, endApproachTime ); -} - -// --------------------------------------------------------------------------- -// write -// --------------------------------------------------------------------------- -// Export the envelope parameter streams represented by this SpcFile to -// the file having the specified filename or path. Export phase-correct -// bandwidth-enhanced envelope parameter streams if enhanced is true -// (the default), or pure sinsoidal streams otherwise. -// -// -// A nonzero endApproachTime indicates that the Partials do not include a -// release or decay, but rather end in a static spectrum corresponding to the -// final Breakpoint values of the partials. The endApproachTime specifies how -// long before the end of the sound the amplitude, frequency, and bandwidth -// values are to be modified to make a gradual transition to the static spectrum. -// -// If the endApproachTime is not specified, it is assumed to be zero, -// corresponding to Partials that decay or release normally. -// -// This version of write is deprecated, but is handy for internal use, -// called by the above write and writeSiunsoidal members. -// -void -SpcFile::write( const std::string & filename, bool enhanced, double endApproachTime ) -{ - if ( endApproachTime < 0 ) - { - Throw( InvalidArgument, "End Approach Time may not be negative." ); - } - - std::ofstream s( filename.c_str(), std::ofstream::binary ); - if ( ! s ) - { - std::string s = "Could not create file \""; - s += filename; - s += "\". Failed to write Spc file."; - Throw( FileIOException, s ); - } - - // have to do this before trying to do anything else: - configureExportStruct( partials_, notenum_, endApproachTime, enhanced ); - - unsigned long dataSize = 0; - - CommonCk commonChunk; - configureCommonCk( commonChunk, getNumSampleFrames(), Nchans, Bps, rate_ ); - dataSize += commonChunk.header.size + sizeof(CkHeader); - - SoundDataCk soundDataChunk; - configureEnvelopeDataCk( soundDataChunk, partials_ ); - dataSize += soundDataChunk.header.size + sizeof(CkHeader); - - InstrumentCk instrumentChunk; - configureInstrumentCk( instrumentChunk, notenum_ ); - dataSize += instrumentChunk.header.size + sizeof(CkHeader); - - MarkerCk markerChunk; - if ( ! markers_.empty() ) - { - configureSosMarkerCk( markerChunk, markers_ ); - dataSize += markerChunk.header.size + sizeof(CkHeader); - } - - SosEnvelopesCk soseChunk; - configureSosEnvelopesCk( soseChunk ); - dataSize += soseChunk.header.size + sizeof(CkHeader); - - ContainerCk containerChunk; - configureContainer( containerChunk, dataSize ); - - try - { - writeContainer( s, containerChunk ); - writeCommonData( s, commonChunk ); - if ( ! markers_.empty() ) - writeMarkerData( s, markerChunk ); - writeInstrumentData( s, instrumentChunk ); - writeSosEnvelopesChunk( s, soseChunk ); - writeSampleData( s, soundDataChunk ); - - s.close(); - } - catch ( Exception & ex ) - { - ex.append( " Failed to write Spc file." ); - throw; - } -} - -// -- access -- - -// --------------------------------------------------------------------------- -// markers -// --------------------------------------------------------------------------- -// Return a reference to the Marker (see Marker.h) container -// for this SpcFile. -// -SpcFile::markers_type & -SpcFile::markers( void ) -{ - return markers_; -} - -const SpcFile::markers_type & -SpcFile::markers( void ) const -{ - return markers_; -} - -// --------------------------------------------------------------------------- -// midiNoteNumber -// --------------------------------------------------------------------------- -// Return the fractional MIDI note number assigned to this SpcFile. -// If the sound has no definable pitch, note number 60.0 is used. -// -double -SpcFile::midiNoteNumber( void ) const -{ - return notenum_; -} - -// --------------------------------------------------------------------------- -// partials -// --------------------------------------------------------------------------- -// Return a read-only (const) reference to the bandwidth-enhanced -// Partials represented by the envelope parameter streams in this SpcFile. -// -const SpcFile::partials_type & -SpcFile::partials( void ) const -{ - return partials_; -} - -// --------------------------------------------------------------------------- -// sampleRate -// --------------------------------------------------------------------------- -// Return the sampling freqency in Hz for the spc data in this -// SpcFile. This is the rate at which Kyma must be running to ensure -// proper playback of bandwidth-enhanced Spc data. -// -double -SpcFile::sampleRate( void ) const -{ - return rate_; -} - -// -- mutation -- - -// --------------------------------------------------------------------------- -// addPartial -// --------------------------------------------------------------------------- -// Add the specified Partial to the enevelope parameter streams -// represented by this SpcFile. -// -// A SpcFile can contain only one Partial having any given (non-zero) -// label, so an added Partial will replace a Partial having the -// same label, if such a Partial exists. -// -// This may throw an InvalidArgument exception if an attempt is made -// to add unlabeled Partials, or Partials labeled higher than the -// allowable maximum. -// -void -SpcFile::addPartial( const Partial & p ) -{ - addPartial( p, p.label() ); -} - -// --------------------------------------------------------------------------- -// addPartial -// --------------------------------------------------------------------------- -// Add a Partial, assigning it the specified label (and position in the -// Spc data). -// -// A SpcFile can contain only one Partial having any given (non-zero) -// label, so an added Partial will replace a Partial having the -// same label, if such a Partial exists. -// -// This may throw an InvalidArgument exception if an attempt is made -// to add unlabeled Partials, or Partials labeled higher than the -// allowable maximum. -// -void -SpcFile::addPartial( const Partial & p, int label ) -{ - if ( p.label() == 0 ) - { - Throw( InvalidArgument, "Spc Partials must be labeled." ); - } - if ( label < 1 ) - { - Throw( InvalidArgument, "Spc Partials must have positive labels." ); - } - if ( label > LargestLabel ) - { - Throw( InvalidArgument, "Spc Partial label is too large, cannot have more than 256." ); - } - - if ( label > partials_.size() ) - { - growPartials( label ); - } - - partials_[label - 1] = p; - partials_[label - 1].setLabel( label ); -} - -// --------------------------------------------------------------------------- -// setMidiNoteNumber -// --------------------------------------------------------------------------- -// Set the fractional MIDI note number assigned to this SpcFile. -// If the sound has no definable pitch, use note number 60.0 (the default). -// -void -SpcFile::setMidiNoteNumber( double nn ) -{ - if ( nn < 0 || nn > 128 ) - { - Throw( InvalidArgument, "MIDI note number outside of the valid range [1,128]" ); - } - notenum_ = nn; -} - -// --------------------------------------------------------------------------- -// setSampleRate -// --------------------------------------------------------------------------- -// Set the sampling freqency in Hz for the spc data in this -// SpcFile. This is the rate at which Kyma must be running to ensure -// proper playback of bandwidth-enhanced Spc data. -// -void -SpcFile::setSampleRate( double rate ) -{ - if ( rate <= 0 ) - { - Throw( InvalidArgument, "Sample rate must be positive." ); - } - rate_ = rate; -} - -// -- helpers -- - -// --------------------------------------------------------------------------- -// growPartials -// --------------------------------------------------------------------------- -// -void -SpcFile::growPartials( partials_type::size_type sz ) -{ - if ( partials_.size() < sz ) - { -#ifdef PO2 - partials_type::size_type po2sz = MinNumPartials; - while ( po2sz < sz ) - { - po2sz *= 2; - } - partials_.resize( po2sz ); -#else - partials_.resize( sz ); -#endif - for ( partials_type::size_type j = 0; j < partials_.size(); ++j ) - { - partials_[j].setLabel( j+1 ); - } - } -} - -// -- export structures -- - -// --------------------------------------------------------------------------- -// Export Structures -// --------------------------------------------------------------------------- -// - -// structure for export information -struct SpcExportInfo -{ - double midipitch; // note number (69.00 = A440) for spc file; - // this is the core parameter, others are, by default, - // computed from this one - double endApproachTime; // in seconds, this indicates how long before the end of the sound the - // amplitude, frequency, and bandwidth values are to be modified to - // make a gradual transition to the spectral content at the end, - // 0.0 indicates no such modifications are to be done - int numPartials; // number of partials in spc file - int fileNumPartials; // the actual number of partials plus padding to make a 2**n value - int enhanced; // true for bandwidth-enhanced spc file, false for pure sines - double startTime; // in seconds, time of first frame in spc file - double endTime; // in seconds, this indicates the time at which to truncate the end - // of the spc file, 0.0 indicates no truncation - double markerTime; // in seconds, this indicates time at which a marker is inserted in the - // spc file, 0.0 indicates no marker is desired - double sampleRate; // in hertz, intended sample rate for synthesis of spc file - double hop; // hop size, based on numPartials and sampleRate - double ampEpsilon; // small amplitude value (related to lsb value in spc file log-amp) -}; - -static struct SpcExportInfo spcEI; // yikky global spc Export information - - -// -- export helpers by Lippold -- - -// --------------------------------------------------------------------------- -// fileNumPartials -// --------------------------------------------------------------------------- -// Find number of partials in SOS file. This is the actual number of partials, -// plus padding to make a 2**n value. -// -static int fileNumPartials( int partials ) -{ - if ( partials <= 32 ) - return 32; - if ( partials <= 64 ) - return 64; - if ( partials <= 128 ) - return 128; - else if ( partials <= 256 ) - return 256; - else if ( partials <= LargestLabel ) - return LargestLabel; - - Throw( FileIOException, "Too many SPC partials!" ); - return LargestLabel; -} - -// --------------------------------------------------------------------------- -// envLog( ) -// --------------------------------------------------------------------------- -// For a range 0 to 1, this returns a log value, 0x0000 to 0xFFFF. -// -static unsigned long envLog( double floatingValue ) -{ - static double coeff = 65535.0 / log( 32768. ); - - return (unsigned long)( coeff * log( 32768.0 * floatingValue + 1.0 ) ); - -} // end of envLog( ) - -// --------------------------------------------------------------------------- -// envExp( ) -// --------------------------------------------------------------------------- -// For a range 0x0000 to 0xFFFF, this returns an exponentiated value in the range 0..1. -// This is the counterpart of SpcFile::envLog(). -// -static double envExp( long intValue ) -{ - static double coeff = 65535.0 / log( 32768. ); - - return ( exp( intValue / coeff ) - 1.0 ) / 32768.0; - -} // end of envExp( ) - -// --------------------------------------------------------------------------- -// getPhaseRefTime -// --------------------------------------------------------------------------- -// Find the time at which to reference phase. -// The time will be shortly after amplitude onset, if we are before the onset. -// -static double getPhaseRefTime( int label, const Partial & p, double time ) -{ -// Keep array of previous values to optimize spc export. -// This depends on this routine being called in increasing-time order. - static double prevPRT[LargestLabel + 1]; - if ( prevPRT[label] > time && time > spcEI.startTime ) - return prevPRT[ label ]; - -// Go forward to nonzero amplitude. - while ( p.amplitudeAt( time, Fade ) < spcEI.ampEpsilon && time < spcEI.endTime + spcEI.hop) - { - time += spcEI.hop; - } - - prevPRT[ label ] = time; - -// Use phase value at initial onset time. - return time; - -} - -// --------------------------------------------------------------------------- -// afbp -// --------------------------------------------------------------------------- -// Find amplitude, frequency, bandwidth, phase value. -// -static void afbp( const Partial & p, double time, double phaseRefTime, - double magMult, double freqMult, - double & amp, double & freq, double & bw, double & phase) -{ - -// Optional endApproachTime processing: -// Approach amp, freq, and bw values at endTime, and stick at endTime amplitude. -// We avoid a sudden transition when using stick-at-end-frame sustains. -// Compute weighting factor between "normal" envelope point and static point. - if ( spcEI.endApproachTime && time > spcEI.endTime - spcEI.endApproachTime ) - { - if ( time > p.endTime() && p.endTime() > spcEI.endTime - 2 * spcEI.hop) - time = p.endTime(); - double wt = ( spcEI.endTime - time ) / spcEI.endApproachTime; - amp = magMult * ( wt * p.amplitudeAt( time, Fade ) + - (1.0 - wt) * p.amplitudeAt( spcEI.endTime, Fade ) ); - freq = freqMult * ( wt * p.frequencyAt( time ) + (1.0 - wt) * p.frequencyAt( spcEI.endTime ) ); - bw = ( wt * p.bandwidthAt( time ) + (1.0 - wt) * p.bandwidthAt( spcEI.endTime ) ); - phase = p.phaseAt( time ); - } - -// If we are before the phase reference time, or on the final frame, -// use zero amp and offset phase. - else if ( time < phaseRefTime - spcEI.hop / 2 || time > spcEI.endTime - spcEI.hop / 2 ) - { - amp = 0.; - freq = freqMult * p.frequencyAt( phaseRefTime ); - bw = 0.; - phase = p.phaseAt( phaseRefTime ) - 2. * Pi * (phaseRefTime - time) * freq; - } - -// Use envelope values at "time". - else - { - amp = magMult * p.amplitudeAt( time, Fade ); - freq = freqMult * p.frequencyAt( time ); - bw = p.bandwidthAt( time ); - phase = p.phaseAt( time ); - } -} - -// --------------------------------------------------------------------------- -// pack -// --------------------------------------------------------------------------- -// Pack envelope breakpoint value for interpretation by Envelope Reader sounds -// in Kyma. The packed result is two 24-bit quantities, lval and rval. -// -// In lval, the log of the sine magnitude occupies the top 8 bits, the log of the -// frequency occupies the bottom 16 bits. -// -// In rval, the log of the noise magnitude occupies the top 8 bits, the scaled -// linear phase occupies the bottom 16 bits. -// -// lval and rval are pointers to 3-bytes each, filled in by this function. -// -static void pack( double amp, double freq, double bw, double phase, - Byte * lbytes, Byte * rbytes ) -{ - -// Set phase for one hop earlier, so that Kyma synthesis target phase is correct. -// Add offset to phase for difference between Kyma and Loris representation. - phase -= 2. * Pi * spcEI.hop * freq; - phase += Pi / 2; - -// Make phase into range 0..1. - phase = std::fmod( phase, 2. * Pi ); - while ( phase < 0. ) // used to be if, I think it should be while - { // -kel 12 May 2006 - phase += 2. * Pi; - } - double zeroToOnePhase = phase / (2. * Pi); - -// Make frequency into range 0..1. - double zeroToOneFreq = freq / 22050.0; // 0..1 , 1 is 22.050 kHz - -// Compute sine magnitude and noise magnitude from amp and bw. - double theSineMag = amp * sqrt( 1. - bw ); - double theNoiseMag = 64.0 * amp * sqrt( bw ); - if (theNoiseMag > 1.0) - theNoiseMag = 1.0; - -// Pack amp and freq into 24 least-significant bits of lval: -// 7 bits of log-sine-amplitude with 16 bits of zero to right. -// 16 bits of log-frequency with 0 bits of zero to right. - unsigned long lval; - lval = ( envLog( theSineMag ) & 0xFE00 ) << 7; - lval |= ( envLog( zeroToOneFreq ) & 0xFFFF ); - -// store in lbytes: -// store the sample bytes in big endian order, -// most significant byte first: - const int BytesPerSample = 3; - for ( int j = BytesPerSample; j > 0; --j ) - { - // mask the lowest byte after shifting: - *(lbytes++) = 0xFF & (lval >> (8*(j-1))); - } - -// Pack noise amp and phase into 24 least-significant bits of rval: -// 7 bits of log-noise-amplitude with 16 bits of zero to right. -// 16 bits of phase with 0 bits of zero to right. - unsigned long rval; - rval = ( envLog( theNoiseMag ) & 0xFE00 ) << 7; - rval |= ( (unsigned long) ( zeroToOnePhase * 0xFFFF ) ); - -// store in rbytes: -// store the sample bytes in big endian order, -// most significant byte first: - for ( int j = BytesPerSample; j > 0; --j ) - { - // mask the lowest byte after shifting: - *(rbytes++) = 0xFF & (rval >> (8*(j-1))); - } -} - -// --------------------------------------------------------------------------- -// packEnvelopes -// --------------------------------------------------------------------------- -// The partials should be labeled and distilled before this is called. -// -static bool notEmpty( const Partial & p ) { return p.size() > 0; } - -static void packEnvelopes( const SpcFile::partials_type & partials, - std::vector< Byte > & bytes ) -{ -// Assert( partials.size() == spcEI.fileNumPartials ); - - int frames = int( ( spcEI.endTime - spcEI.startTime ) / spcEI.hop ) + 1; - unsigned long dataSize = - frames * spcEI.fileNumPartials * ( 24 / 8 ) * (spcEI.enhanced ? 2 : 1); - bytes.clear(); - bytes.reserve( dataSize ); - - // get the reference partial; the lowest-nonzero-labeled partial with any breakpoints - SpcFile::partials_type::const_iterator pos = - std::find_if( partials.begin(), partials.end(), notEmpty ); - Assert( pos != partials.end() ); - const Partial & refPar = *pos; - int refLabel = refPar.label(); - Assert( (refLabel - 1) == (pos - partials.begin()) ); - - // write out one frame at a time: - for (double tim = spcEI.startTime; tim <= spcEI.endTime; tim += spcEI.hop ) - { - // for each frame, write one value for every partial: - // (this loop extends to the pad partials) - for (unsigned int label = 1; label <= spcEI.fileNumPartials; ++label ) - { - double amp, freq, bw, phase; - // find partial with the correct label - // if partial with the correct is empty, - // frequency-multiply the reference partial -#ifndef PO2 - if ( label > partials.size() || partials[ label - 1 ].size() == 0 ) -#else - if ( partials[ label - 1 ].size() == 0 ) -#endif - { - // find the reference time for the phase - double phaseRefTime = getPhaseRefTime( label, refPar, tim ); - - // find amplitude, frequency, bandwidth, phase value - double freqMult = (double) label / (double) refLabel; - double magMult = 0.0; - afbp( refPar, tim, phaseRefTime, magMult, freqMult, amp, freq, bw, phase ); - } - else - { - // find the reference time for the phase - double phaseRefTime = getPhaseRefTime( label, partials[ label - 1 ], tim ); - - // find amplitude, frequency, bandwidth, phase value - afbp( partials[ label - 1 ], tim, phaseRefTime, 1, 1, amp, freq, bw, phase ); - } - - // pack log amplitude and log frequency into 24-bit lval, - // log bandwidth and phase into 24-bit rval: - Byte leftbytes[3], rightbytes[3]; - pack( amp, freq, bw, phase, leftbytes, rightbytes); - - // pack integer samples into the Byte vector without - // byte swapping, they are already correctly packed - // (see pack above): - bytes.insert( bytes.end(), leftbytes, leftbytes + 3 ); - if ( spcEI.enhanced ) - { - bytes.insert( bytes.end(), rightbytes, rightbytes + 3 ); - } - } - } - - Assert( bytes.size() == dataSize ); -} - -// --------------------------------------------------------------------------- -// configureEnvelopeDataCk -// --------------------------------------------------------------------------- -// Configure a special SoundDataCk for exporting Spc envelopes. -// -static void -configureEnvelopeDataCk( SoundDataCk & ck, const SpcFile::partials_type & partials ) -{ - packEnvelopes( partials, ck.sampleBytes ); - - ck.header.id = SoundDataId; - - // size is everything after the header: - ck.header.size = sizeof(Uint_32) + // offset - sizeof(Uint_32) + // block size - ck.sampleBytes.size(); // sample data - - // no block alignment: - ck.offset = 0; - ck.blockSize = 0; -} - -// --------------------------------------------------------------------------- -// configureSosMarkerCk -// --------------------------------------------------------------------------- -// Spc needs a special version of this, because Marker times have to be -// rounded to the nearest frame. -// -void -configureSosMarkerCk( MarkerCk & ck, const std::vector< Marker > & markers ) -{ - ck.header.id = MarkerId; - - // accumulate data size - Uint_32 dataSize = sizeof(Uint_16); // num markers - - ck.numMarkers = markers.size(); - ck.markers.resize( markers.size() ); - for ( int j = 0; j < markers.size(); ++j ) - { - MarkerCk::Marker & m = ck.markers[j]; - m.markerID = j+1; - //m.position = Uint_32((markers[j].time() * srate) + 0.5); - - // align marker with nearest frame time: - m.position = Uint_32( markers[j].time() / spcEI.hop ) - * spcEI.fileNumPartials - * ( spcEI.enhanced ? 2 : 1 ); - - m.markerName = markers[j].name(); - - #define MAX_PSTRING_CHARS 254 - if ( m.markerName.size() > MAX_PSTRING_CHARS ) - m.markerName.resize( MAX_PSTRING_CHARS ); - - // the size of a pascal string is the number of - // characters plus the size byte, plus the terminal '\0': - // - // Actualy, at least one web source indicates that Pascal - // strings are not null-terminated, but that they _are_ - // padded with an extra (not part of the count) byte - // if necessary to ensure that the total length (including - // count) is even, and this seems to work better with other - // programs (e.g. Kyma) - if ( m.markerName.size()%2 == 0 ) - m.markerName += '\0'; - dataSize += sizeof(Uint_16) + sizeof(Uint_32) + (m.markerName.size() + 1); - } - - // must be an even number of bytes - if ( dataSize%2 ) - ++dataSize; - - ck.header.size = dataSize; -} - - -// --------------------------------------------------------------------------- -// configureSosEnvelopesCk -// --------------------------------------------------------------------------- -// Configure a the application-specific chunk for exporting Spc envelopes. -// -static void -configureSosEnvelopesCk( SosEnvelopesCk & ck ) -{ - ck.header.id = ApplicationSpecificId; - - // size is everything after the header: - ck.header.size = sizeof(Uint_32) + // signature - sizeof(Uint_32) + // enhanced - sizeof(Uint_32) + // validPartials - // this last bit is a big, obsolete array, that - // we now use two positions in, an they aren't - // even the first two! Truly nasty. - 4*LargestLabel + 8 * sizeof(Int_32);// initPhase[] et al - - ck.signature = SosEnvelopesId; - - ck.enhanced = spcEI.enhanced; - - // the number of partials is doubled in bandwidth-enhanced spc files - ck.validPartials = spcEI.numPartials * ( spcEI.enhanced ? 2 : 1 ); - - // resolution in microseconds - ck.resolution = long( 1000000.0 * spcEI.hop ); - - // all partials quasiharmonic - // the number of partials is doubled in bandwidth-enhanced spc files - ck.quasiHarmonic = spcEI.numPartials * ( spcEI.enhanced ? 2 : 1); - -} - -// --------------------------------------------------------------------------- -// writeSosEnvelopesChunk -// --------------------------------------------------------------------------- -// -std::ostream & -writeSosEnvelopesChunk( std::ostream & s, const SosEnvelopesCk & ck ) -{ - // write it out: - try - { - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.header.id ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.header.size ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.signature ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.enhanced ); - BigEndian::write( s, 1, sizeof(Int_32), (char *)&ck.validPartials ); - - // The SOSresultion and SOSquasiHarmonic fields are in the phase table memory. - //BigEndian::write( s, initPhaseLth, sizeof(Int_32), (char *)&ck.initPhase[0] ); - static const int InitPhaseLth = ( LargestLabel + 8 ); - Int_32 bogus[ InitPhaseLth ]; // obsolete initial phase array - std::fill( bogus, bogus + InitPhaseLth, 0 ); - bogus[ ck.validPartials ] = ck.resolution; - bogus[ ck.validPartials + 1 ] = ck.quasiHarmonic; - BigEndian::write( s, InitPhaseLth, sizeof(Int_32), (char *)bogus ); - } - catch( FileIOException & ex ) - { - ex.append( "Failed to write AIFF file Container chunk." ); - throw; - } - - return s; - -} - -// --------------------------------------------------------------------------- -// computeHop -// --------------------------------------------------------------------------- -// Find the hop size, based on number of partials and sample rate. -// -static double computeHop( int numPartials, double sampleRate ) -{ - return 2 * numPartials / sampleRate; -} - - -// --------------------------------------------------------------------------- -// computeStartTime -// --------------------------------------------------------------------------- -// Find the start time: the earliest time of any labeled partial. -// -static double computeStartTime( const SpcFile::partials_type & pars ) -{ - double startTime = 1000.; - for ( SpcFile::partials_type::const_iterator pIter = pars.begin(); pIter != pars.end(); ++pIter ) - if ( pIter->size() > 0 && startTime > pIter->startTime() && pIter->label() > 0 ) - startTime = pIter->startTime(); - return startTime; -} - - -// --------------------------------------------------------------------------- -// computeEndTime -// --------------------------------------------------------------------------- -// Find the end time: the latest time of any labeled partial. -// -static double computeEndTime( const SpcFile::partials_type & pars ) -{ - double endTime = -1000.; - for ( SpcFile::partials_type::const_iterator pIter = pars.begin(); pIter != pars.end(); ++pIter ) - if ( pIter->size() > 0 && endTime < pIter->endTime() && pIter->label() > 0 ) - endTime = pIter->endTime(); - return endTime; -} - - -// --------------------------------------------------------------------------- -// computeNumPartials -// --------------------------------------------------------------------------- -// Find the number of partials. -// -static long computeNumPartials( const SpcFile::partials_type & pars ) -{ - -// We purposely consider partials with no breakpoints, to allow -// a larger number of partials than actually have data. - int numPartials = 0; - for ( SpcFile::partials_type::const_iterator pIter = pars.begin(); pIter != pars.end(); ++pIter ) - if ( numPartials < pIter->label() ) - numPartials = pIter->label(); - -// To ensure a reasonable hop time, make at least 32 partials. - return numPartials ? std::max( 32, numPartials ) : 0; -} - -// --------------------------------------------------------------------------- -// configureExportStruct -// --------------------------------------------------------------------------- -static void -configureExportStruct( const SpcFile::partials_type & plist, double midipitch, - double endApproachTime, int enhanced ) -{ - // note number (69.00 = A440) for spc file - spcEI.midipitch = midipitch; - - // enhanced indicates a bandwidth-enhanced spc file; by default it is true. - // if enhanced is false, no bandwidth or noise information is exported. - spcEI.enhanced = enhanced; - - // endApproachTime is in seconds; by default it is zero (and has no effect). - // a nonzero endApproachTime indicates that the plist does not include a - // release, but rather ends in a static spectrum corresponding to the final - // breakpoint values of the partials. the endApproachTime specifies how - // long before the end of the sound the amplitude, frequency, and bandwidth - // values are to be modified to make a gradual transition to the static spectrum. - spcEI.endApproachTime = endApproachTime; - - // number of partials in spc file - spcEI.numPartials = computeNumPartials( plist ); - spcEI.fileNumPartials = fileNumPartials( spcEI.numPartials ); - - // start and end time of spc file - spcEI.startTime = computeStartTime( plist ); - spcEI.endTime = computeEndTime( plist ); - - // in seconds, this indicates time at which a marker is inserted - // in the spc file, 0.0 indicates no marker. this is not being used currently. - spcEI.markerTime = 0.; - - // in hertz, intended sample rate for synthesis of spc file - spcEI.sampleRate = 44100.; - - // compute hop size - spcEI.hop = computeHop( spcEI.numPartials, spcEI.sampleRate ); - - // compute ampEpsilon, a small amplitude value twice the lsb value - // of log amp in packed spc format. - spcEI.ampEpsilon = 2. * envExp( 0x200 ); - - // Max number of partials is due to (arbitrary) size of initPhase[]. - if ( spcEI.numPartials < 1 || spcEI.numPartials > LargestLabel ) - Throw( FileIOException, "Partials must be distilled and labeled between 1 and 512." ); - - debugger << "startTime = " << spcEI.startTime << " endTime = " << spcEI.endTime - << " hop = " << spcEI.hop << " partials = " << spcEI.numPartials << endl; -} - -// --------------------------------------------------------------------------- -// getNumSampleFrames -// --------------------------------------------------------------------------- -// The number of exported sample frames is computed from data stored in -// the icky global export struct. -// -static unsigned long getNumSampleFrames( void ) -{ - int frames = int( ( spcEI.endTime - spcEI.startTime ) / spcEI.hop ) + 1; - return frames * spcEI.fileNumPartials * ( spcEI.enhanced ? 2 : 1 ); -} - -// -- import helpers by Lippold -- -// --------------------------------------------------------------------------- -// processEnhancedPoint -// --------------------------------------------------------------------------- -// Add ehanced-spc breakpoint to existing Loris partials. -// -static void -processEnhancedPoint( Byte * leftbytes, Byte * rightbytes, - const double frameTime, - Partial & par ) -{ -// represent bytes as 24 bit integers: - const int BytesPerSample = 3; - - // assign the leading byte, so that the sign - // is preserved: - long left = static_cast(*(leftbytes++)); - for ( int j = 1; j < BytesPerSample; ++j ) - { - // OR bytes after the most significant, so - // that their sign is ignored: - left = (left << 8) + (unsigned char)*(leftbytes++); - } - - long right = static_cast(*(rightbytes++)); - for ( int j = 1; j < BytesPerSample; ++j ) - { - // OR bytes after the most significant, so - // that their sign is ignored: - right = (right << 8) + (unsigned char)*(rightbytes++); - } -// -// Unpack values. -// - double freq = envExp( left & 0xffff ) * 22050.0; - double sineMag = envExp( (left >> 7) & 0xfe00 ); - double noiseMag = envExp( (right >> 7) & 0xfe00 ) / 64.; - double phase = ( right & 0xffff ) * ( 2. * Pi / 0xffff ); - - double total = sineMag * sineMag + noiseMag * noiseMag; - - double amp = sqrt( total ); - - double noise = 0.; - if (total != 0.) - noise = noiseMag * noiseMag / total; - if (noise > 1.) - noise = 1.; - - phase -= Pi / 2.; - if (phase < 0.) - phase += 2. * Pi; - -// -// Create a new breakpoint and insert it. -// - Breakpoint newbp( freq, amp, noise, phase ); - par.insert( frameTime, newbp ); -} - -// --------------------------------------------------------------------------- -// processSineOnlyPoint -// --------------------------------------------------------------------------- -// Add sine-only spc breakpoint to existing Loris partials. -// -static void -processSineOnlyPoint( Byte * bytes, - const double frameTime, - Partial & par ) -{ -// represent bytes as 24 bit integers: - const int BytesPerSample = 3; - - // assign the leading byte, so that the sign - // is preserved: - long packed = static_cast(*(bytes++)); - for ( int j = 1; j < BytesPerSample; ++j ) - { - // OR bytes after the most significant, so - // that their sign is ignored: - packed = (packed << 8) + (unsigned char)*(bytes++); - } - -// -// Unpack values. -// - double freq = envExp( packed & 0xffff ) * 22050.0; - double amp = envExp( (packed >> 7) & 0xfe00 ); - double noise = 0.; - double phase = 0.; - -// -// Create a new breakpoint and insert it. -// - Breakpoint newbp( freq, amp, noise, phase ); - par.insert( frameTime, newbp ); -} - -// --------------------------------------------------------------------------- -// readSpcData -// --------------------------------------------------------------------------- -// -void -SpcFile::readSpcData( const std::string & filename ) -{ - ContainerCk containerChunk; - CommonCk commonChunk; - SoundDataCk soundDataChunk; - InstrumentCk instrumentChunk; - MarkerCk markerChunk; - SosEnvelopesCk soseChunk; - - try - { - std::ifstream s( filename.c_str(), std::ifstream::binary ); - - // the Container chunk must be first, read it: - readChunkHeader( s, containerChunk.header ); - if( containerChunk.header.id != ContainerId ) - Throw( FileIOException, "Found no Container chunk." ); - readContainer( s, containerChunk, containerChunk.header.size ); - - // read other chunks, we are only interested in - // the Common chunk, the Sound Data chunk, the Markers: - CkHeader h; - while ( readChunkHeader( s, h ) ) - { - switch (h.id) - { - case CommonId: - readCommonData( s, commonChunk, h.size ); - if ( commonChunk.channels != 1 ) - { - Throw( FileIOException, - "Loris only processes single-channel AIFF samples files." ); - } - if ( commonChunk.bitsPerSample != 8 && - commonChunk.bitsPerSample != 16 && - commonChunk.bitsPerSample != 24 && - commonChunk.bitsPerSample != 32 ) - { - Throw( FileIOException, "Unrecognized sample size." ); - } - break; - case SoundDataId: - readSampleData( s, soundDataChunk, h.size ); - break; - case InstrumentId: - readInstrumentData( s, instrumentChunk, h.size ); - break; - case MarkerId: - readMarkerData( s, markerChunk, h.size ); - break; - case ApplicationSpecificId: - readApplicationSpecifcData( s, soseChunk, h.size ); - break; - default: - s.ignore( h.size ); - } - } - - if ( ! commonChunk.header.id || ! soundDataChunk.header.id ) - { - Throw( FileIOException, - "Reached end of file before finding both a Common chunk and a Sound Data chunk." ); - } - if ( soseChunk.signature != SosEnvelopesId ) - { - Throw( FileIOException, - "Reached end of file before finding a Spc Envelope Data chunk, this must not be a Spc file." ); - } - } - catch ( Exception & ex ) - { - ex.append( " Failed to read Spc file." ); - throw; - } - - // all the chunks have been read, use them to initialize - // the SpcFile members: - rate_ = commonChunk.srate; - - // why was this like this: - // double rate = commonChunk.srate; - - if ( instrumentChunk.header.id ) - { - notenum_ = instrumentChunk.baseNote; - notenum_ -= 0.01 * instrumentChunk.detune; - } - - // extract information from SOSe chunk: - // enhanced file format has number of partials doubled - // sine-only file format has proper number of partials - bool enhanced = soseChunk.enhanced != 0; - int numPartials = enhanced ? soseChunk.validPartials / 2 : soseChunk.validPartials; - int numFrames = commonChunk.sampleFrames / ( fileNumPartials( numPartials ) * ( enhanced ? 2 : 1 ) ); - double hop = soseChunk.resolution * 0.000001; // resolution is in microseconds - - // read markers, need to compute times corresponding to - // spc frames: - if ( markerChunk.header.id ) - { - for ( int j = 0; j < markerChunk.numMarkers; ++j ) - { - MarkerCk::Marker & m = markerChunk.markers[j]; - double markerTime = m.position * hop / ( fileNumPartials( numPartials ) * ( enhanced ? 2 : 1 ) ); - markers_.push_back( Marker( markerTime, m.markerName ) ); - } - } - - - // check for valid file - if ( numPartials == 0 || commonChunk.bitsPerSample != 24 ) - Throw( FileIOException, "Not an SPC file." ); - if ( numPartials < MinNumPartials || numPartials > LargestLabel ) - Throw( FileIOException, "Bad number of partials in SPC file." ); - - // check the number of bytes of Spc data: - const int BytesPerSample = 3; - const int PredictedNumBytes = - BytesPerSample * numFrames * fileNumPartials( numPartials ) * ( enhanced ? 2 : 1 ); - if ( soundDataChunk.sampleBytes.size() != PredictedNumBytes ) - { - notifier << "Found " << soundDataChunk.sampleBytes.size() << " bytes of " - << commonChunk.bitsPerSample << "-bit sample data." << endl; - notifier << "Header says there should be " << PredictedNumBytes - << "." << endl; - } - - // process SPC data points - partials_.clear(); - growPartials( numPartials ); - Byte * bytes = &soundDataChunk.sampleBytes.front(); - for ( int frame = 0; frame < numFrames; ++frame ) - { - for ( int partial = 0; partial < fileNumPartials( numPartials ); ++partial ) - { - if (enhanced) - { - Byte * lbytes = bytes; - bytes += BytesPerSample; - Byte * rbytes = bytes; - bytes += BytesPerSample; - if ( partial < partials_.size() ) - processEnhancedPoint( lbytes, rbytes, frame * hop, partials_[partial] ); - } - else - { - if ( partial < partials_.size() ) - processSineOnlyPoint( bytes, frame * hop, partials_[partial] ); - bytes += BytesPerSample; - } - } - } -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/SpcFile.h b/loris_library/Source/src/SpcFile.h deleted file mode 100644 index 118b30d..0000000 --- a/loris_library/Source/src/SpcFile.h +++ /dev/null @@ -1,368 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpcFile.h - * - * Definition of SpcFile class for Partial import and export for - * real-time synthesis in Kyma. - * - * Spc files always represent a number of Partials that is a power of - * two. This is not necessary for purely-sinusoidal files, but might be - * (not clear) for enhanced data to be properly processed in Kyma. - * - * All of this is kind of disgusting right now. This code has evolved - * somewhat randomly, and we are awaiting full support for bandwidth- - * enhanced data in Kyma.. - * - * Kelly Fitz, 8 Jan 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "Marker.h" -#include "Partial.h" - -#if defined(NO_TEMPLATE_MEMBERS) -#include "PartialList.h" -#endif - -#include -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class SpcFile -// -//! Class SpcFile represents a collection of reassigned bandwidth-enhanced -//! Partial data in a SPC-format envelope stream data file, used by the -//! real-time bandwidth-enhanced additive synthesizer implemented on the -//! Symbolic Sound Kyma Sound Design Workstation. Class SpcFile manages -//! file I/O and conversion between Partials and envelope parameter streams. -// -class SpcFile -{ -// -- public interface -- -public: - -// -- types -- - - //! the type of the container of Markers - //! stored with an SpcFile - typedef std::vector< Marker > markers_type; - - //! the type of the container of Partials - //! stored with an SpcFile - typedef std::vector< Partial > partials_type; - -// -- construction -- - - //! Initialize an instance of SpcFile by importing envelope parameter - //! streams from the file having the specified filename or path. - //! - //! \param filename the name of the file to import - explicit SpcFile( const std::string & filename ); - - //! Initialize an instance of SpcFile with copies of the Partials - //! on the specified half-open (STL-style) range. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. - //! - //! \param begin_partials the beginning of a range of Partials to prepare - //! for Spc export - //! \param end_partials the end of a range of Partials to prepare - //! for Spc export - //! \param midiNoteNum the fractional MIDI note number, if specified - //! (default is 60) -#if !defined(NO_TEMPLATE_MEMBERS) - template - SpcFile( Iter begin_partials, Iter end_partials, double midiNoteNum = 60 ); -#else - SpcFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double midiNoteNum = 60 ); -#endif - - //! Initialize an instance of SpcFile having the specified fractional - //! MIDI note number, and no Partials (or envelope parameter streams). - //! - //! \param midiNoteNum the fractional MIDI note number, if specified - //! (default is 60) - explicit SpcFile( double midiNoteNum = 60 ); - - // copy, assign, and delete are compiler-generated - -// -- access -- - - //! Return a reference to the MarkerContainer (see Marker.h) for this SpcFile. - markers_type & markers( void ); - - //! Return a reference to the MarkerContainer (see Marker.h) for this SpcFile. - const markers_type & markers( void ) const; - - //! Return the fractional MIDI note number assigned to this SpcFile. - //! If the sound has no definable pitch, note number 60.0 is used. - double midiNoteNumber( void ) const; - - //! Return a read-only (const) reference to the bandwidth-enhanced - //! Partials represented by the envelope parameter streams in this SpcFile. - const partials_type & partials( void ) const; - - //! Return the sampling freqency in Hz for the spc data in this - //! SpcFile. This is the rate at which Kyma must be running to ensure - //! proper playback of bandwidth-enhanced Spc data. - double sampleRate( void ) const; - -// -- mutation -- - - //! Add the specified Partial to the enevelope parameter streams - //! represented by this SpcFile. - //! - //! A SpcFile can contain only one Partial having any given (non-zero) - //! label, so an added Partial will replace a Partial having the - //! same label, if such a Partial exists. - //! - //! This may throw an InvalidArgument exception if an attempt is made - //! to add unlabeled Partials, or Partials labeled higher than the - //! allowable maximum. - //! - //! \param p the Partial to add to this SpcFile - void addPartial( const Loris::Partial & p ); - - //! Add a Partial, assigning it the specified label (and position in the - //! Spc data). - //! - //! A SpcFile can contain only one Partial having any given (non-zero) - //! label, so an added Partial will replace a Partial having the - //! same label, if such a Partial exists. - //! - //! This may throw an InvalidArgument exception if an attempt is made - //! to add unlabeled Partials, or Partials labeled higher than the - //! allowable maximum. - //! - //! \param p the Partial to add to this SpcFile - //! \param label the label to associate with this Partial in - //! the Spc file (the Partial's own label is ignored). - void addPartial( const Loris::Partial & p, int label ); - - //! Add all Partials on the specified half-open (STL-style) range - //! to the enevelope parameter streams represented by this SpcFile. - //! - //! A SpcFile can contain only one Partial having any given (non-zero) - //! label, so an added Partial will replace a Partial having the - //! same label, if such a Partial exists. - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts - //! only PartialList::const_iterator arguments. - //! - //! This may throw an InvalidArgument exception if an attempt is made - //! to add unlabeled Partials, or Partials labeled higher than the - //! allowable maximum. - //! - //! \param begin_partials the beginning of a range of Partials - //! to add to this Spc file - //! \param end_partials the end of a range of Partials - //! to add to this Spc file -#if !defined(NO_TEMPLATE_MEMBERS) - template - void addPartials( Iter begin_partials, Iter end_partials ); -#else - void addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ); -#endif - - //! Set the fractional MIDI note number assigned to this SpcFile. - //! If the sound has no definable pitch, use note number 60.0 - //! (the default). - void setMidiNoteNumber( double nn ); - - //! Set the sampling freqency in Hz for the spc data in this - //! SpcFile. This is the rate at which Kyma must be running to ensure - //! proper playback of bandwidth-enhanced Spc data. - //! - //! The default sample rate is 44100 Hz. - void setSampleRate( double rate ); - -// -- export -- - - //! Export the phase-correct bandwidth-enhanced envelope parameter - //! streams represented by this SpcFile to the file having the specified - //! filename or path. - //! - //! A nonzero endApproachTime indicates that the Partials do not include a - //! release or decay, but rather end in a static spectrum corresponding to the - //! final Breakpoint values of the partials. The endApproachTime specifies how - //! long before the end of the sound the amplitude, frequency, and bandwidth - //! values are to be modified to make a gradual transition to the static spectrum. - //! - //! If the endApproachTime is not specified, it is assumed to be zero, - //! corresponding to Partials that decay or release normally. - //! - //! \param filename the name of the file to create - //! \param endApproachTime the duration in seconds of the gradual transition - //! to a static spectrum at the end of the sound (default 0) - void write( const std::string & filename, double endApproachTime = 0 ); - - //! Export the pure sinsoidal (omitting phase and bandwidth data) envelope - //! parameter streams represented by this SpcFile to the file having the - //! specified filename or path. - //! - //! A nonzero endApproachTime indicates that the Partials do not include a - //! release or decay, but rather end in a static spectrum corresponding to the - //! final Breakpoint values of the partials. The endApproachTime specifies how - //! long before the end of the sound the amplitude, frequency, and bandwidth - //! values are to be modified to make a gradual transition to the static spectrum. - //! - //! If the endApproachTime is not specified, it is assumed to be zero, - //! corresponding to Partials that decay or release normally. - //! - //! \param filename the name of the file to create - //! \param endApproachTime the duration in seconds of the gradual transition - //! to a static spectrum at the end of the sound (default 0) - void writeSinusoidal( const std::string & filename, double endApproachTime = 0 ); - - //! Export the envelope parameter streams represented by this SpcFile to - //! the file having the specified filename or path. Export phase-correct - //! bandwidth-enhanced envelope parameter streams if enhanced is true - //! (the default), or pure sinsoidal streams otherwise. - //! - //! A nonzero endApproachTime indicates that the Partials do not include a - //! release or decay, but rather end in a static spectrum corresponding to the - //! final Breakpoint values of the partials. The endApproachTime specifies how - //! long before the end of the sound the amplitude, frequency, and bandwidth - //! values are to be modified to make a gradual transition to the static spectrum. - //! - //! If the endApproachTime is not specified, it is assumed to be zero, - //! corresponding to Partials that decay or release normally. - //! - //! \deprecated This version of write is deprecated, use the two-argument - //! versions write and writeSinusoidal. - //! - //! \param filename the name of the file to create - //! \param enhanced flag indicating whether to export enhanced (true) - //! or sinusoidal (false) data - //! \param endApproachTime the duration in seconds of the gradual transition - //! to a static spectrum at the end of the sound (default 0) - void write( const std::string & filename, bool enhanced, - double endApproachTime = 0 ); - -private: -// -- implementation -- - partials_type partials_; //! Partials to store in Spc format - markers_type markers_; //! AIFF Markers - - double notenum_; //! fractional MIDI note number - double rate_; //! sample rate in Hz at which the data plays at the - //! correction default pitch - - static const int MinNumPartials; //! the minimum number of Partials to export (32) - //! (if necessary, extra empty (silent) Partials - //! will be exported to make up the difference between - //! the size of partials_ and the next larger power - //! of two, not less than MinNumPartials - static const double DefaultRate; //! the default Spc export sample rate in Hz (44kHz) - -// -- helpers -- - void readSpcData( const std::string & filename ); - void growPartials( partials_type::size_type sz ); - -}; // end of class SpcFile - - -// --------------------------------------------------------------------------- -// constructor from Partial range -// --------------------------------------------------------------------------- -//! Initialize an instance of SpcFile with copies of the Partials -//! on the specified half-open (STL-style) range. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. -//! -//! \param begin_partials the beginning of a range of Partials to prepare -//! for Spc export -//! \param end_partials the end of a range of Partials to prepare -//! for Spc export -//! \param midiNoteNum the fractional MIDI note number, if specified -//! (default is 60) -#if !defined(NO_TEMPLATE_MEMBERS) -template< typename Iter > -SpcFile::SpcFile( Iter begin_partials, Iter end_partials, double midiNoteNum ) : -#else -SpcFile::SpcFile( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials, - double midiNoteNum ) : -#endif -// initializers: - notenum_( midiNoteNum ), - rate_( DefaultRate ) -{ - growPartials( MinNumPartials ); - addPartials( begin_partials, end_partials ); -} - -// --------------------------------------------------------------------------- -// addPartials -// --------------------------------------------------------------------------- -//! Add all Partials on the specified half-open (STL-style) range -//! to the enevelope parameter streams represented by this SpcFile. -//! -//! A SpcFile can contain only one Partial having any given (non-zero) -//! label, so an added Partial will replace a Partial having the -//! same label, if such a Partial exists. -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts -//! only PartialList::const_iterator arguments. -//! -//! This may throw an InvalidArgument exception if an attempt is made -//! to add unlabeled Partials, or Partials labeled higher than the -//! allowable maximum. -//! -//! \param begin_partials the beginning of a range of Partials -//! to add to this Spc file -//! \param end_partials the end of a range of Partials -//! to add to this Spc file -#if !defined(NO_TEMPLATE_MEMBERS) -template -void SpcFile::addPartials( Iter begin_partials, Iter end_partials ) -#else -void SpcFile::addPartials( PartialList::const_iterator begin_partials, - PartialList::const_iterator end_partials ) -#endif -{ - while ( begin_partials != end_partials ) - { - // do not try to add unlabeled Partials, or - // Partials labeled beyond 256: - if ( 0 != begin_partials->label() && 257 > begin_partials->label() ) - { - addPartial( *begin_partials ); - } - ++begin_partials; - } -} - -} // end of namespace Loris - - diff --git a/loris_library/Source/src/SpectralPeakSelector.cpp b/loris_library/Source/src/SpectralPeakSelector.cpp deleted file mode 100644 index a6cbc15..0000000 --- a/loris_library/Source/src/SpectralPeakSelector.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpectralPeakSelector.C - * - * Implementation of a class representing a policy for selecting energy - * peaks in a reassigned spectrum to be used in Partial formation. - * - * Kelly Fitz, 28 May 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "SpectralPeakSelector.h" - - -#include "Breakpoint.h" -#include "Notifier.h" -#include "ReassignedSpectrum.h" - - -#include // for abs and fabs - - -// define this to use local minima in frequency -// reassignment to detect "peaks", otherwise -// magnitude peaks are used. -#define USE_REASSIGNMENT_MINS 1 -//#undef USE_REASSIGNMENT_MINS - - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// construction - constant resolution -// --------------------------------------------------------------------------- -SpectralPeakSelector::SpectralPeakSelector( double srate, double maxTimeCorrection ) : - mSampleRate( srate ), - mMaxTimeOffset( maxTimeCorrection ) -{ -} - -// --------------------------------------------------------------------------- -// selectPeaks -// --------------------------------------------------------------------------- -// Collect and return magnitude peaks in the lower half of the spectrum, -// ignoring those having frequencies below the specified minimum, and -// those having large time corrections. -// -// If the minimumFrequency is unspecified, 0 Hz is used. -// -// There are two strategies for doing. Probably each one should be a -// separate class, but for now, they are just separate functions. - -Peaks -SpectralPeakSelector::selectPeaks( ReassignedSpectrum & spectrum, - double minFrequency ) -{ -#if defined(USE_REASSIGNMENT_MINS) && USE_REASSIGNMENT_MINS - - return selectReassignmentMinima( spectrum, minFrequency ); - -#else - - return selectMagnitudePeaks( spectrum, minFrequency ); - -#endif -} - -// --------------------------------------------------------------------------- -// selectReassignmentMinima (private) -// --------------------------------------------------------------------------- -Peaks -SpectralPeakSelector::selectReassignmentMinima( ReassignedSpectrum & spectrum, - double minFrequency ) -{ - using namespace std; // for abs and fabs - - const double sampsToHz = mSampleRate / spectrum.size(); - const double oneOverSR = 1. / mSampleRate; - const double minFreqSample = minFrequency / sampsToHz; - const double maxCorrectionSamples = mMaxTimeOffset * mSampleRate; - - Peaks peaks; - - int start_j = 1, end_j = (spectrum.size() / 2) - 2; - - double fsample = start_j; - do - { - fsample = spectrum.reassignedFrequency( start_j++ ); - } while( fsample < minFreqSample ); - - for ( int j = start_j; j < end_j; ++j ) - { - - // look for changes in the frequency reassignment, - // from positive to negative correction, indicating - // a concentration of energy in the spectrum: - double next_fsample = spectrum.reassignedFrequency( j+1 ); - if ( fsample > j && next_fsample < j + 1 ) - { - // choose the smaller correction of fsample or next_fsample: - // (could also choose the larger magnitude?) - double freq; - int peakidx; - if ( (fsample-j) < (j+1-next_fsample) ) - { - freq = fsample * sampsToHz; - peakidx = j; - } - else - { - freq = next_fsample * sampsToHz; - peakidx = j+1; - } - - // still possible that the frequency winds up being - // below the specified minimum - if ( freq >= minFrequency ) - { - // keep only peaks with small time corrections: - double timeCorrectionSamps = spectrum.reassignedTime( peakidx ); - if ( fabs(timeCorrectionSamps) < maxCorrectionSamples ) - { - double mag = spectrum.reassignedMagnitude( peakidx ); - double phase = spectrum.reassignedPhase( peakidx ); - - // this will be overwritten later in analysis, - // might be ignored altogether, only used if the - // mixed derivative convergence indicator is stored - // as bandwidth in Analyzer: - double bw = spectrum.convergence( j ); - - - // also store the corrected peak time in seconds, won't - // be able to compute it later: - double time = timeCorrectionSamps * oneOverSR; - Breakpoint bp( freq, mag, bw, phase ); - peaks.push_back( SpectralPeak( time, bp ) ); - } - } - - } - fsample = next_fsample; - } - - /* - debugger << "SpectralPeakSelector::selectReassignmentMinima: found " - << peaks.size() << " peaks" << endl; - */ - - return peaks; - -} - -// --------------------------------------------------------------------------- -// selectMagnitudePeaks (private) -// --------------------------------------------------------------------------- -Peaks -SpectralPeakSelector::selectMagnitudePeaks( ReassignedSpectrum & spectrum, - double minFrequency ) -{ - using namespace std; // for abs and fabs - - const double sampsToHz = mSampleRate / spectrum.size(); - const double oneOverSR = 1. / mSampleRate; - const double minFreqSample = minFrequency / sampsToHz; - const double maxCorrectionSamples = mMaxTimeOffset * mSampleRate; - - Peaks peaks; - - int start_j = 1, end_j = (spectrum.size() / 2) - 2; - - double fsample = start_j; - do - { - fsample = spectrum.reassignedFrequency( start_j++ ); - } while( fsample < minFreqSample ); - - for ( int j = start_j; j < end_j; ++j ) - { - if ( spectrum.reassignedMagnitude(j) > spectrum.reassignedMagnitude(j-1) && - spectrum.reassignedMagnitude(j) > spectrum.reassignedMagnitude(j+1) ) - { - // skip low-frequency peaks: - double fsample = spectrum.reassignedFrequency( j ); - if ( fsample < minFreqSample ) - continue; - - // skip peaks with large time corrections: - double timeCorrectionSamps = spectrum.reassignedTime( j ); - if ( fabs(timeCorrectionSamps) > maxCorrectionSamples ) - continue; - - double mag = spectrum.reassignedMagnitude( j ); - double phase = spectrum.reassignedPhase( j ); - - // this will be overwritten later in analysis, - // might be ignored altogether, only used if the - // mixed derivative convergence indicator is stored - // as bandwidth in Analyzer: - double bw = spectrum.convergence( j ); - - // also store the corrected peak time in seconds, won't - // be able to compute it later: - double time = timeCorrectionSamps * oneOverSR; - Breakpoint bp ( fsample * sampsToHz, mag, bw, phase ); - peaks.push_back( SpectralPeak( time, bp ) ); - - } // end if itsa peak - } - - /* - debugger << "SpectralPeakSelector::selectMagnitudePeaks: found " - << peaks.size() << " peaks" << endl; - */ - return peaks; -} - - -} // end of namespace Loris diff --git a/loris_library/Source/src/SpectralPeakSelector.h b/loris_library/Source/src/SpectralPeakSelector.h deleted file mode 100644 index c55056e..0000000 --- a/loris_library/Source/src/SpectralPeakSelector.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef INCLUDE_SPECTRALPEAKSELECTOR_H -#define INCLUDE_SPECTRALPEAKSELECTOR_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpectralPeakSelector.h - * - * Definition of a class representing a policy for selecting energy - * peaks in a reassigned spectrum to be used in Partial formation. - * - * Kelly Fitz, 28 May 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "SpectralPeaks.h" - -// begin namespace -namespace Loris { - -class ReassignedSpectrum; - -// --------------------------------------------------------------------------- -// class SpectralPeakSelector -// -// A class representing the process of selecting -// peaks (ridges) on a reassigned time-frequency surface. -// -class SpectralPeakSelector -{ -// --- interface --- -public: - // construction: - SpectralPeakSelector( double srate, double maxTimeCorrection ); - - // Collect and return magnitude peaks in the lower half of the spectrum, - // ignoring those having frequencies below the specified minimum (in Hz), and - // those having large time corrections. - // - // If the minimumFrequency is unspecified, 0 Hz is used. - // - // There are two strategies for doing. Probably each one should be a - // separate class, but for now, they are just separate functions. - Peaks selectPeaks( ReassignedSpectrum & spectrum, double minFrequency = 0 ); - - -// --- implementation --- -private: - - // There are two strategies for doing. Probably each one should be a - // separate class, but for now, they are just separate functions. - // - // Currently, the reassignment minima are used. - - Peaks selectReassignmentMinima( ReassignedSpectrum & spectrum, double minFrequency ); - Peaks selectMagnitudePeaks( ReassignedSpectrum & spectrum, double minFrequency ); - - -// --- member data --- - - double mSampleRate; - double mMaxTimeOffset; - - -}; // end of class SpectralPeakSelector - -} // end of namespace Loris - -#endif /* ndef INCLUDE_SPECTRALPEAKSELECTOR_H */ diff --git a/loris_library/Source/src/SpectralPeaks.h b/loris_library/Source/src/SpectralPeaks.h deleted file mode 100644 index e5103cf..0000000 --- a/loris_library/Source/src/SpectralPeaks.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef INCLUDE_SPECTRALPEAKS_H -#define INCLUDE_SPECTRALPEAKS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpectralPeaks.h - * - * Definition of a type representing a collection (vector) of - * reassigned spectral peaks or ridges. Shared by analysis policies. - * - * Kelly Fitz, 29 May 2003 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "Breakpoint.h" - -#include - -// begin namespace -namespace Loris { - -// define a spectral peak data structure -// -// HEY -// Clean this mess up! Upgrade this struct into a class that can -// store more kinds of information (like reassignment values), and -// creates a Breakpoint when needed. - -class SpectralPeak -{ -private: - - double m_time; - Breakpoint m_breakpoint; - -public: - - // --- lifecycle --- - - SpectralPeak( double t, const Breakpoint & bp ) : m_time( t ), m_breakpoint( bp ) {} - - - // --- access --- - - double time( void ) const { return m_time; } - - double amplitude( void ) const { return m_breakpoint.amplitude(); } - double frequency( void ) const { return m_breakpoint.frequency(); } - double bandwidth( void ) const { return m_breakpoint.bandwidth(); } - - // --- mutation --- - - void setAmplitude( double x ) { m_breakpoint.setAmplitude(x); } - void setBandwidth( double x ) { m_breakpoint.setBandwidth(x); } - - // this REALLY shouldn't be in here... - void addNoiseEnergy( double enoise ) { m_breakpoint.addNoiseEnergy(enoise); } - - // --- Breakpoint creation --- - - Breakpoint createBreakpoint( void ) const { return m_breakpoint; } - - // --- comparitors --- - - // Comparitor for sorting spectral peaks in order of - // increasing frequency, or finding maximum frequency. - - static bool sort_increasing_freq( const SpectralPeak & lhs, - const SpectralPeak & rhs ) - { - return lhs.frequency() < rhs.frequency(); - } - - // predicate used for sorting peaks in order of decreasing amplitude: - static bool sort_greater_amplitude( const SpectralPeak & lhs, - const SpectralPeak & rhs ) - { - return lhs.amplitude() > rhs.amplitude(); - } -}; - -// define the structure used to collect spectral peaks: -typedef std::vector< SpectralPeak > Peaks; - - - -} // end of namespace Loris - -#endif /* ndef INCLUDE_SPECTRALPEAKS_H */ diff --git a/loris_library/Source/src/SpectralSurface.cpp b/loris_library/Source/src/SpectralSurface.cpp deleted file mode 100644 index 69e7f5e..0000000 --- a/loris_library/Source/src/SpectralSurface.cpp +++ /dev/null @@ -1,376 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpectralSurface.C - * - * Implementation of class SpectralSurface, a class representing - * a smoothed time-frequency surface that can be used to - * perform cross-synthesis, the filtering of one sound by the - * time-varying spectrum of another. - * - * Kelly Fitz, 21 Dec 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "SpectralSurface.h" - -#include "BreakpointUtils.h" -#include "LorisExceptions.h" -#include "Notifier.h" -#include "Partial.h" - -#include -#include - -namespace Loris { - -// --------------------------------------------------------------------------- -// peakAmp - local helper for addPartialAux -// --------------------------------------------------------------------------- -static double peakAmp( const Partial & p ) -{ - if ( 0 == p.numBreakpoints() ) - { - return 0; - } - return std::max_element( p.begin(), p.end(), - BreakpointUtils::compareAmplitudeLess() - ).breakpoint().amplitude(); -} - -// --------------------------------------------------------------------------- -// findemfaster - local helper -// --------------------------------------------------------------------------- -static std::pair< const Partial *, const Partial * > -findemfaster( double freq, double time, const std::vector< Partial > & parray ) -{ - static std::vector< Partial >::size_type cacheLastHit = 0; - - std::vector< Partial >::size_type i = cacheLastHit; - const Partial * p1 = 0; - const Partial * p2 = 0; - if ( parray[i].frequencyAt( time ) < freq ) - { - // search up the list - while ( i < parray.size() && parray[i].frequencyAt( time ) < freq ) - { - ++i; - } - if ( i > 0 ) - { - p1 = &parray[i-1]; - cacheLastHit = i-1; - } - else - { - p1 = 0; - cacheLastHit = 0; - } - if ( i < parray.size() ) - { - p2 = &parray[i]; - } - else - { - p2 = 0; - } - } - else - { - // search down the list - while ( i > 0 && parray[i].frequencyAt( time ) > freq ) - { - --i; - } - if ( i > 0 || parray[i].frequencyAt( time ) < freq ) - { - p1 = &parray[i]; - cacheLastHit = i; - } - else - { - p1 = 0; - cacheLastHit = 0; - } - if ( i + 1 < parray.size() ) - { - p2 = &parray[i+1]; - } - else - { - p2 = 0; - } - } - // debugger << "findemfaster caching " << cacheLastHit << endl; - return std::make_pair(p1, p2); -} - -// --------------------------------------------------------------------------- -// smoothInTime - local helper -// --------------------------------------------------------------------------- -static double smoothInTime( const Partial & p, double t ) -{ - const double spanT = 30; // ms - const int steps = 13; - const double incrT = (2 * spanT) / (steps - 1); - - double a = p.amplitudeAt( t ); - if ( 0 == a ) - { - for (double dehr = -spanT; dehr <= spanT; dehr += incrT ) - { - a += p.amplitudeAt( t + ( .001*dehr ) ); - } - a = a / steps; - } - return a; -} - -// --------------------------------------------------------------------------- -// surfaceAt - local helper -// --------------------------------------------------------------------------- -static double surfaceAt( double f, double t, const std::vector< Partial > & parray ) -{ - std::pair< const Partial *, const Partial * > both = findemfaster( f, t, parray ); - const Partial * p1 = both.first; - const Partial * p2 = both.second; - - double moo1 = 0, moo2 = 0, interp = 0; - - if ( 0 != p1 && 0 != p2 ) - { - interp = (f - p1->frequencyAt( t )) / ( p2->frequencyAt( t ) - p1->frequencyAt( t ) ); - moo1 = smoothInTime( *p1, t ); - moo2 = smoothInTime( *p2, t ); - } - else if ( 0 != p2 ) - { - interp = 1; - moo2 = smoothInTime( *p2, t ); - moo1 = moo2; - } - else if ( 0 != p1 ) - { - interp = 1. / (f - p1->frequencyAt( t )); - moo1 = smoothInTime( *p1, t ); - moo2 = 0; - } - else - { - moo1 = moo2 = interp = 0; - } - return ((1-interp)*moo1 + interp*moo2); -} - -// --------------------------------------------------------------------------- -// scaleAmplitudes -// --------------------------------------------------------------------------- -//! Scale the amplitude of every Breakpoint in a Partial -//! according to the amplitude of the spectral surface -//! at the corresponding time and frequency. -//! -//! \param p the Partial to modify -// -void SpectralSurface::scaleAmplitudes( Partial & p ) -{ - const double FreqScale = 1.0 / mStretchFreq; - const double TimeScale = 1.0 / mStretchTime; - - Partial::iterator iter; - for ( iter = p.begin(); iter != p.end(); ++iter ) - { - Breakpoint & bp = iter.breakpoint(); - double f = bp.frequency(); - double t = iter.time(); - - double ampscale = surfaceAt( FreqScale * f, TimeScale * t, mPartials ) / mMaxSurfaceAmp; - - double a = bp.amplitude() * ( (1.-mEffect) + (mEffect*ampscale) ); - bp.setAmplitude( a ); - } -} - -// --------------------------------------------------------------------------- -// setAmplitudes -// --------------------------------------------------------------------------- -//! Set the amplitude of every Breakpoint in a Partial -//! equal to the amplitude of the spectral surface -//! at the corresponding time and frequency. -//! -//! \param p the Partial to modify -// -void SpectralSurface::setAmplitudes( Partial & p ) -{ - const double FreqScale = 1.0 / mStretchFreq; - const double TimeScale = 1.0 / mStretchTime; - - Partial::iterator iter; - for ( iter = p.begin(); iter != p.end(); ++iter ) - { - Breakpoint & bp = iter.breakpoint(); - if ( 0 != bp.amplitude() ) - { - double f = bp.frequency(); - double t = iter.time(); - - double surfaceAmp = surfaceAt( FreqScale * f, TimeScale * t, mPartials ); - double a = ( bp.amplitude()*(1.-mEffect) ) + ( mEffect*surfaceAmp ); - bp.setAmplitude( a ); - } - } -} - -// --- access/mutation --- - -// --------------------------------------------------------------------------- -// frequencyStretch -// --------------------------------------------------------------------------- -//! Return the amount of strecthing in the frequency dimension -//! (default 1, no stretching). Values greater than 1 stretch -//! the surface in the frequency dimension, values less than 1 -//! (but greater than 0) compress the surface in the frequency -//! dimension. -// -double SpectralSurface::frequencyStretch( void ) const -{ - return mStretchFreq; -} - -// --------------------------------------------------------------------------- -// timeStretch -// --------------------------------------------------------------------------- -//! Return the amount of strecthing in the time dimension -//! (default 1, no stretching). Values greater than 1 stretch -//! the surface in the time dimension, values less than 1 -//! (but greater than 0) compress the surface in the time -//! dimension. -// -double SpectralSurface::timeStretch( void ) const -{ - return mStretchTime; -} - -// --------------------------------------------------------------------------- -// effect -// --------------------------------------------------------------------------- -//! Return the amount of effect applied by scaleAmplitudes -//! and setAmplitudes (default 1, full effect). Values -//! less than 1 (but greater than 0) reduce the amount of -//! amplitude modified performed by application of the -//! surface. (This is rarely a good way of controlling the -//! amount of the effect.) -// -double SpectralSurface::effect( void ) const -{ - return mEffect; -} - -// --------------------------------------------------------------------------- -// setFrequencyStretch -// --------------------------------------------------------------------------- -//! Set the amount of strecthing in the frequency dimension -//! (default 1, no stretching). Values greater than 1 stretch -//! the surface in the frequency dimension, values less than 1 -//! (but greater than 0) compress the surface in the frequency -//! dimension. -//! -//! \pre stretch must be positive -//! \param stretch the new stretch factor for the frequency dimension -// -void SpectralSurface::setFrequencyStretch( double stretch ) -{ - if ( 0 > stretch ) - { - Throw( InvalidArgument, - "SpectralSurface frequency stretch must be non-negative." ); - } - mStretchFreq = stretch; -} - -// --------------------------------------------------------------------------- -// setTimeStretch -// --------------------------------------------------------------------------- -//! Set the amount of strecthing in the time dimension -//! (default 1, no stretching). Values greater than 1 stretch -//! the surface in the time dimension, values less than 1 -//! (but greater than 0) compress the surface in the time -//! dimension. -//! -//! \pre stretch must be positive -//! \param stretch the new stretch factor for the time dimension -// -void SpectralSurface::setTimeStretch( double stretch ) -{ - if ( 0 > stretch ) - { - Throw( InvalidArgument, - "SpectralSurface time stretch must be non-negative." ); - } - mStretchTime = stretch; -} - -// --------------------------------------------------------------------------- -// setEffect -// --------------------------------------------------------------------------- -//! Set the amount of effect applied by scaleAmplitudes -//! and setAmplitudes (default 1, full effect). Values -//! less than 1 (but greater than 0) reduce the amount of -//! amplitude modified performed by application of the -//! surface. (This is rarely a good way of controlling the -//! amount of the effect.) -//! -//! \pre effect must be between 0 and 1, inclusive -//! \param effect the new factor controlling the amount of -//! amplitude modification performed by scaleAmplitudes -//! and setAmplitudes -// -void SpectralSurface::setEffect( double effect ) -{ - if ( 0 > effect || 1 < effect ) - { - Throw( InvalidArgument, - "SpectralSurface effect must be non-negative and not greater than 1." ); - } - mEffect = effect; -} - -// --- private helpers --- - -// --------------------------------------------------------------------------- -// addPartialAux -// --------------------------------------------------------------------------- -// Helper function used by constructor for adding Partials one -// by one. Still have to sort after adding all the Partials -// using this helper! This just adds the Partial and keeps track -// of the largest amplitude seen so far. -// -void SpectralSurface::addPartialAux( const Partial & p ) -{ - mPartials.push_back( p ); - mMaxSurfaceAmp = std::max( mMaxSurfaceAmp, peakAmp( p ) ); -} - - -} //end namespace - diff --git a/loris_library/Source/src/SpectralSurface.h b/loris_library/Source/src/SpectralSurface.h deleted file mode 100644 index 3291f3d..0000000 --- a/loris_library/Source/src/SpectralSurface.h +++ /dev/null @@ -1,370 +0,0 @@ -#ifndef INCLUDE_SPECTRALSURFACE_H -#define INCLUDE_SPECTRALSURFACE_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * SpectralSurface.h - * - * Definition of class SpectralSurface, a class representing - * a smoothed time-frequency surface that can be used to - * perform cross-synthesis, the filtering of one sound by the - * time-varying spectrum of another. - * - * Kelly Fitz, 21 Dec 2005 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "LorisExceptions.h" -#include "Partial.h" -#include "PartialList.h" -#include "PartialUtils.h" // for compareLabelLess - -#include // for sort -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// Class SpectralSurface -// -//! SpectralSurface represents a smoothed time-frequency surface that -//! can be used to perform cross-synthesis, the filtering of one sound -//! by the time-varying spectrum of another. -// -class SpectralSurface -{ -// -- public interface -- -public: - -// -- lifecycle -- - - //! Contsruct a new SpectralSurface from a sequence of distilled - //! Partials. - //! - //! \pre the specified Partials must be channelized and distilled. - //! \param b the beginning of the sequence of Partials - //! \param e the end of the sequence of Partials - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - SpectralSurface( Iter b, Iter e ); -#else - inline - SpectralSurface( PartialList::iterator b, PartialList::iterator e ); -#endif - - // use compiler-generated copy/assign/destroy - -// --- operations --- - - //! Scale the amplitude of every Breakpoint in a Partial - //! according to the amplitude of the spectral surface - //! at the corresponding time and frequency. - //! - //! \param p the Partial to modify - void scaleAmplitudes( Partial & p ); - - //! Scale the amplitudes of a sequence of Partials - //! according to the amplitude of the spectral surface - //! at the corresponding times and frequencies, - //! performing cross-synthesis, the filtering of one - //! sound (the sequence of Partials) by the time-varying - //! spectrum of another sound (the Partials used to - //! construct the surface). The surface is stretched - //! in time and frequency according to the values of - //! the two stretch factors (default 1, no stretching) - //! and the amount of the effect is governed by the - //! `effect' parameter (default 1, full effect). - //! - //! \param b the beginning of the sequence of Partials - //! \param e the end of the sequence of Partials - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void scaleAmplitudes( Iter b, Iter e ); -#else - inline - void scaleAmplitudes( PartialList::iterator b, PartialList::iterator e ); -#endif - - //! Set the amplitude of every Breakpoint in a Partial - //! equal to the amplitude of the spectral surface - //! at the corresponding time and frequency. - //! - //! \param p the Partial to modify - void setAmplitudes( Partial & p ); - - //! Set the amplitudes of a sequence of Partials - //! equal to the amplitude of the spectral surface - //! at the corresponding times and frequencies. - //! This can be used to perform formant-corrected - //! pitch shifting of a sound: construct the surface - //! from the unmodified Partials, perform the pitch - //! shift on the Partials, then apply the surface - //! to the shifted Partials using setAmplitudes. - //! The surface is stretched - //! in time and frequency according to the values of - //! the two stretch factors (default 1, no stretching) - //! and the amount of the effect is governed by the - //! `effect' parameter (default 1, full effect). - //! - //! \param b the beginning of the sequence of Partials - //! \param e the end of the sequence of Partials - //! - //! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e - //! must be PartialList::iterators, otherwise they can be any type - //! of iterators over a sequence of Partials. -#if ! defined(NO_TEMPLATE_MEMBERS) - template - void setAmplitudes( Iter b, Iter e ); -#else - inline - void setAmplitudes( PartialList::iterator b, PartialList::iterator e ); -#endif - -// --- access/mutation --- - - //! Return the amount of strecthing in the frequency dimension - //! (default 1, no stretching). Values greater than 1 stretch - //! the surface in the frequency dimension, values less than 1 - //! (but greater than 0) compress the surface in the frequency - //! dimension. - double frequencyStretch( void ) const; - - //! Return the amount of strecthing in the time dimension - //! (default 1, no stretching). Values greater than 1 stretch - //! the surface in the time dimension, values less than 1 - //! (but greater than 0) compress the surface in the time - //! dimension. - double timeStretch( void ) const; - - //! Return the amount of effect applied by scaleAmplitudes - //! and setAmplitudes (default 1, full effect). Values - //! less than 1 (but greater than 0) reduce the amount of - //! amplitude modified performed by application of the - //! surface. (This is rarely a good way of controlling the - //! amount of the effect.) - double effect( void ) const; - - //! Set the amount of strecthing in the frequency dimension - //! (default 1, no stretching). Values greater than 1 stretch - //! the surface in the frequency dimension, values less than 1 - //! (but greater than 0) compress the surface in the frequency - //! dimension. - //! - //! \pre stretch must be positive - //! \param stretch the new stretch factor for the frequency dimension - void setFrequencyStretch( double stretch ); - - //! Set the amount of strecthing in the time dimension - //! (default 1, no stretching). Values greater than 1 stretch - //! the surface in the time dimension, values less than 1 - //! (but greater than 0) compress the surface in the time - //! dimension. - //! - //! \pre stretch must be positive - //! \param stretch the new stretch factor for the time dimension - void setTimeStretch( double stretch ); - - //! Set the amount of effect applied by scaleAmplitudes - //! and setAmplitudes (default 1, full effect). Values - //! less than 1 (but greater than 0) reduce the amount of - //! amplitude modified performed by application of the - //! surface. (This is rarely a good way of controlling the - //! amount of the effect.) - //! - //! \pre effect must be between 0 and 1, inclusive - //! \param effect the new factor controlling the amount of - //! amplitude modification performed by scaleAmplitudes - //! and setAmplitudes - void setEffect( double effect ); - -private: - -// -- instance variables -- - - std::vector< Partial > mPartials; //! the Partials comprising the surface are - //! stored in a vector for easy random access - double mStretchFreq; //! stretch factor for the frequency dimension - double mStretchTime; //! stretch factor for the time dimension - double mEffect; //! factor for controlling the amount of - //! of the effect applied in setAmplitudes and - //! scaleAmplitudes: 0 gives unmodified amplitudes - //! 1 gives fully modified amplitudes. - double mMaxSurfaceAmp; //! the maximum amplitude of any Breakpoint on - //! the surface, used for normalizing the surface - //! amplitude for scaleAmplitudes - -// --- private helpers --- - - // helper used by constructor for adding Partials one by one - void addPartialAux( const Partial & p ); - -}; - -// --------------------------------------------------------------------------- -// constructor -// --------------------------------------------------------------------------- -//! Contsruct a new SpectralSurface from a sequence of distilled -//! Partials. -//! -//! \pre the specified Partials must be channelized and distilled. -//! \param b the beginning of the sequence of Partials -//! \param e the end of the sequence of Partials -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -SpectralSurface::SpectralSurface( Iter b, Iter e ) : -#else -inline -SpectralSurface::SpectralSurface( PartialList::iterator b, - PartialList::iterator e ) : -#endif - mStretchFreq( 1.0 ), - mStretchTime( 1.0 ), - mEffect( 1.0 ), - mMaxSurfaceAmp( 0.0 ) -{ - // add only labeled Partials: - while ( b != e ) - { - if ( b->label() != 0 ) - { - addPartialAux( *b ); - } - ++b; - } - - // complain if the Partials were not distilled - if ( mPartials.empty() ) - { - Throw( InvalidArgument, "Partals need to be distilled to build a SpectralSurface" ); - } - - if ( 0 == mMaxSurfaceAmp ) - { - Throw( InvalidArgument, "The SpectralSurface is zero amplitude everywhere!" ); - } - - // sort by label - std::sort( mPartials.begin(), mPartials.end(), PartialUtils::compareLabelLess() ); -} - - -// --------------------------------------------------------------------------- -// scaleAmplitudes -// --------------------------------------------------------------------------- -//! Scale the amplitudes of a sequence of Partials -//! according to the amplitude of the spectral surface -//! at the corresponding times and frequencies, -//! performing cross-synthesis, the filtering of one -//! sound (the sequence of Partials) by the time-varying -//! spectrum of another sound (the Partials used to -//! construct the surface). The surface is stretched -//! in time and frequency according to the values of -//! the two stretch factors (default 1, no stretching) -//! and the amount of the effect is governed by the -//! `effect' parameter (default 1, full effect). -//! -//! \param b the beginning of the sequence of Partials -//! \param e the end of the sequence of Partials -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void SpectralSurface::scaleAmplitudes( Iter b, Iter e ) -#else -inline -void SpectralSurface::scaleAmplitudes( PartialList::iterator b, - PartialList::iterator e ) -#endif -{ - while ( b != e ) - { - // debugger << b->label() << endl; - scaleAmplitudes( *b ); - ++b; - } -} - -// --------------------------------------------------------------------------- -// setAmplitudes -// --------------------------------------------------------------------------- -//! Set the amplitudes of a sequence of Partials -//! equal to the amplitude of the spectral surface -//! at the corresponding times and frequencies. -//! This can be used to perform formant-corrected -//! pitch shifting of a sound: construct the surface -//! from the unmodified Partials, perform the pitch -//! shift on the Partials, then apply the surface -//! to the shifted Partials using setAmplitudes. -//! The surface is stretched -//! in time and frequency according to the values of -//! the two stretch factors (default 1, no stretching) -//! and the amount of the effect is governed by the -//! `effect' parameter (default 1, full effect). -//! -//! \param b the beginning of the sequence of Partials -//! \param e the end of the sequence of Partials -//! -//! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e -//! must be PartialList::iterators, otherwise they can be any type -//! of iterators over a sequence of Partials. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void SpectralSurface::setAmplitudes( Iter b, Iter e ) -#else -inline -void SpectralSurface::setAmplitudes( PartialList::iterator b, - PartialList::iterator e ) -#endif -{ - while ( b != e ) - { - // debugger << b->label() << endl; - setAmplitudes( *b ); - ++b; - } -} - -} // namespace Loris - -#endif /* ndef INCLUDE_SPECTRALSURFACE_H */ - diff --git a/loris_library/Source/src/Synthesizer.cpp b/loris_library/Source/src/Synthesizer.cpp deleted file mode 100644 index b1b607d..0000000 --- a/loris_library/Source/src/Synthesizer.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Synthesizer.C - * - * Implementation of class Loris::SynthesizerSynthesizer, a synthesizer of - * bandwidth-enhanced Partials. - * - * Kelly Fitz, 16 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "Synthesizer.h" -#include "Oscillator.h" -#include "Breakpoint.h" -#include "BreakpointUtils.h" -#include "Envelope.h" -#include "LorisExceptions.h" -#include "Notifier.h" -#include "Partial.h" -#include "Resampler.h" -#include "phasefix.h" - -#include -#include - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - -// begin namespace -namespace Loris { - - -// --------------------------------------------------------------------------- -// Synthesizer constructor -// --------------------------------------------------------------------------- -//! Construct a Synthesizer using the default parameters and sample -//! buffer (a standard library vector). Since Partials generated by the -//! Loris Analyzer generally begin and end at non-zero amplitude, zero-amplitude -//! Breakpoints are inserted at either end of the Partial, at a temporal -//! distance equal to the fade time, to reduce turn-on and turn-off -//! artifacts. -//! -//! \sa Synthesizer::Parameters -//! -//! \param buffer The vector (of doubles) into which rendered samples -//! should be accumulated. -//! \throw InvalidArgument if any of the parameters is invalid. -Synthesizer::Synthesizer( std::vector & buffer ) : - m_sampleBuffer( & buffer ), - m_fadeTimeSec( DefaultParameters().fadeTime ), - m_srateHz( DefaultParameters().sampleRate ) -{ -} - - -// --------------------------------------------------------------------------- -// Synthesizer constructor -// --------------------------------------------------------------------------- -//! Construct a Synthesizer using the specified parameters and sample -//! buffer (a standard library vector). Since Partials generated by the -//! Loris Analyzer generally begin and end at non-zero amplitude, zero-amplitude -//! Breakpoints are inserted at either end of the Partial, at a temporal -//! distance equal to the fade time, to reduce turn-on and turn-off -//! artifacts. If the fade time is unspecified, the default value of one -//! millisecond (0.001 seconds) is used. -//! -//! \param params A Parameters struct storing the configuration of -//! Synthesizer parameters. -//! \param buffer The vector (of doubles) into which rendered samples -//! should be accumulated. -//! \throw InvalidArgument if any of the parameters is invalid. -// -Synthesizer::Synthesizer( Parameters params, std::vector & buffer ) : - m_sampleBuffer( & buffer ) -{ - // make sure that the parameters are valid before proceeding - if ( IsValidParameters( params ) ) - { - m_fadeTimeSec = params.fadeTime; - m_srateHz = params.sampleRate; - m_osc.filter() = params.filter; - } -} - -// --------------------------------------------------------------------------- -// Synthesizer constructor -// --------------------------------------------------------------------------- -//! Construct a Synthesizer using the specified sampling rate, sample -//! buffer (a standard library vector), and the default fade time -//! stored in the DefaultParameters. Since Partials generated by the Loris -//! Analyzer generally begin and end at non-zero amplitude, zero-amplitude -//! Breakpoints are inserted at either end of the Partial, at a temporal -//! distance equal to the fade time, to reduce turn-on and turn-off -//! artifacts. -//! -//! \param srate The rate (Hz) at which to synthesize samples -//! (must be positive). -//! \param buffer The vector (of doubles) into which rendered samples -//! should be accumulated. -//! \throw InvalidArgument if the specfied sample rate is non-positive. -Synthesizer::Synthesizer( double samplerate, std::vector & buffer ) : - m_sampleBuffer( & buffer ), - m_fadeTimeSec( DefaultParameters().fadeTime ), - m_srateHz( samplerate ) -{ - // check to make sure that the sample rate is valid: - if ( m_srateHz <= 0. ) - { - Throw( InvalidArgument, "Synthesizer sample rate must be positive." ); - } - - // assign the default bw enhancement filter to the Oscillator - m_osc.filter() = DefaultParameters().filter; - -} - -// --------------------------------------------------------------------------- -// Synthesizer constructor -// --------------------------------------------------------------------------- -//! Construct a Synthesizer using the specified sampling rate, sample -//! buffer (a standard library vector), and Partial -//! fade time (in seconds). Since Partials generated by the Loris Analyzer -//! generally begin and end at non-zero amplitude, zero-amplitude -//! Breakpoints are inserted at either end of the Partial, at a temporal -//! distance equal to the fade time, to reduce turn-on and turn-off -//! artifacts. If the fade time is unspecified, the default value of one -//! millisecond (0.001 seconds) is used. -//! -//! \param samplerate The rate (Hz) at which to synthesize samples -//! (must be positive). -//! \param buffer The vector (of doubles) into which rendered samples -//! should be accumulated. -//! \param fade The Partial fade time in seconds (must be non-negative). -//! \throw InvalidArgument if the specfied sample rate is non-positive. -//! \throw InvalidArgument if the specified fade time is negative. -Synthesizer::Synthesizer( double samplerate, std::vector & buffer, - double fade ) : - m_sampleBuffer( & buffer ), - m_fadeTimeSec( fade ), - m_srateHz( samplerate ) -{ - // check to make sure that the sample rate is valid: - if ( m_srateHz <= 0. ) - { - Throw( InvalidArgument, "Synthesizer sample rate must be positive." ); - } - - // check to make sure that the specified fade time - // is valid: - if ( m_fadeTimeSec < 0. ) - { - Throw( InvalidArgument, - "Synthesizer Partial fade time must be non-negative." ); - } - - // assign the default bw enhancement filter to the Oscillator - m_osc.filter() = DefaultParameters().filter; - -} - -// -- synthesis -- - -// --------------------------------------------------------------------------- -// synthesize -// --------------------------------------------------------------------------- -//! Synthesize a bandwidth-enhanced sinusoidal Partial. Zero-amplitude -//! Breakpoints are inserted at either end of the Partial to reduce -//! turn-on and turn-off artifacts, as described above. The synthesizer -//! will resize the buffer as necessary to accommodate all the samples, -//! including the fade out. Previous contents of the buffer are not -//! overwritten. Partials with start times earlier than the Partial fade -//! time will have shorter onset fades. Partials are not rendered at -//! frequencies above the half-sample rate. -//! -//! \param p The Partial to synthesize. -//! \return Nothing. -//! \pre The partial must have non-negative start time. -//! \post This Synthesizer's sample buffer (vector) has been -//! resized to accommodate the entire duration of the -//! Partial, p, including fade out at the end. -//! \throw InvalidPartial if the Partial has negative start time. -// -void -Synthesizer::synthesize( Partial p ) -{ - if ( p.numBreakpoints() == 0 ) - { - debugger << "Synthesizer ignoring a partial that contains no Breakpoints" << endl; - return; - } - - if ( p.startTime() < 0 ) - { - Throw( InvalidPartial, "Tried to synthesize a Partial having start time less than 0." ); - } - - debugger << "synthesizing Partial from " << p.startTime() * m_srateHz - << " to " << p.endTime() * m_srateHz << " starting phase " - << p.initialPhase() << " starting frequency " - << p.first().frequency() << endl; - - // better to compute this only once: - const double OneOverSrate = 1. / m_srateHz; - - - // use a Resampler to quantize the Breakpoint times and - // correct the phases: - Resampler quantizer( OneOverSrate ); - quantizer.setPhaseCorrect( true ); - quantizer.quantize( p ); - - - // resize the sample buffer if necessary: - typedef unsigned long index_type; - index_type endSamp = index_type( ( p.endTime() + m_fadeTimeSec ) * m_srateHz ); - if ( endSamp+1 > m_sampleBuffer->size() ) - { - // pad by one sample: - m_sampleBuffer->resize( endSamp+1 ); - } - - // compute the starting time for synthesis of this Partial, - // m_fadeTimeSec before the Partial's startTime, but not before 0: - double itime = ( m_fadeTimeSec < p.startTime() ) ? ( p.startTime() - m_fadeTimeSec ) : 0.; - index_type currentSamp = index_type( (itime * m_srateHz) + 0.5 ); // cheap rounding - - // reset the oscillator: - // all that really needs to happen here is setting the frequency - // correctly, the phase will be reset again in the loop over - // Breakpoints below, and the amp and bw can start at 0. - m_osc.resetEnvelopes( BreakpointUtils::makeNullBefore( p.first(), p.startTime() - itime ), m_srateHz ); - - // cache the previous frequency (in Hz) so that it - // can be used to reset the phase when necessary - // in the sample computation loop below (this saves - // having to recompute from the oscillator's radian - // frequency): - double prevFrequency = p.first().frequency(); - - // synthesize linear-frequency segments until - // there aren't any more Breakpoints to make segments: - double * bufferBegin = &( m_sampleBuffer->front() ); - for ( Partial::const_iterator it = p.begin(); it != p.end(); ++it ) - { - index_type tgtSamp = index_type( (it.time() * m_srateHz) + 0.5 ); // cheap rounding - Assert( tgtSamp >= currentSamp ); - - // if the current oscillator amplitude is - // zero, and the target Breakpoint amplitude - // is not, reset the oscillator phase so that - // it matches exactly the target Breakpoint - // phase at tgtSamp: - if ( m_osc.amplitude() == 0. ) - { - // recompute the phase so that it is correct - // at the target Breakpoint (need to do this - // because the null Breakpoint phase was computed - // from an interval in seconds, not samples, so - // it might be inaccurate): - // - // double favg = 0.5 * ( prevFrequency + it.breakpoint().frequency() ); - // double dphase = 2 * Pi * favg * ( tgtSamp - currentSamp ) / m_srateHz; - // - double dphase = Pi * ( prevFrequency + it.breakpoint().frequency() ) - * ( tgtSamp - currentSamp ) * OneOverSrate; - m_osc.setPhase( it.breakpoint().phase() - dphase ); - } - - m_osc.oscillate( bufferBegin + currentSamp, bufferBegin + tgtSamp, - it.breakpoint(), m_srateHz ); - - currentSamp = tgtSamp; - - // remember the frequency, may need it to reset the - // phase if a Null Breakpoint is encountered: - prevFrequency = it.breakpoint().frequency(); - } - - // render a fade out segment: - m_osc.oscillate( bufferBegin + currentSamp, bufferBegin + endSamp, - BreakpointUtils::makeNullAfter( p.last(), m_fadeTimeSec ), m_srateHz ); - -} - -// -- sample access -- - -// --------------------------------------------------------------------------- -// samples (const) -// --------------------------------------------------------------------------- -//! Return a const reference to the sample buffer used (not -//! owned) by this Synthesizer. -const std::vector & -Synthesizer::samples( void ) const -{ - return *m_sampleBuffer; -} - -// --------------------------------------------------------------------------- -// samples (non-const) -// --------------------------------------------------------------------------- -//! Return a reference to the sample buffer used (not -//! owned) by this Synthesizer. -std::vector & -Synthesizer::samples( void ) -{ - return *m_sampleBuffer; -} - -// -- parameter access and mutation -- - -// --------------------------------------------------------------------------- -// fadeTime -// --------------------------------------------------------------------------- -//! Return this Synthesizer's Partial fade time, in seconds. -double -Synthesizer::fadeTime( void ) const -{ - return m_fadeTimeSec; -} - -// --------------------------------------------------------------------------- -// sampleRate -// --------------------------------------------------------------------------- -//! Return the sampling rate (in Hz) for this Synthesizer. -double -Synthesizer::sampleRate( void ) const -{ - return m_srateHz; -} - - -// --------------------------------------------------------------------------- -// setFadeTime -// --------------------------------------------------------------------------- -//! Set this Synthesizer's fade time to the specified value -//! (in seconds, must be non-negative). -//! -//! \param t The new Partial fade time. -//! \throw InvalidArgument if the specified fade time is negative. -void -Synthesizer::setFadeTime( double partialFadeTime ) -{ - // check to make sure that the specified fade time - // is valid: - if ( partialFadeTime < 0. ) - { - Throw( InvalidArgument, "Synthesizer Partial fade time must be non-negative." ); - } - - m_fadeTimeSec = partialFadeTime; -} - -// --------------------------------------------------------------------------- -// setSampleRate -// --------------------------------------------------------------------------- -//! Set this Synthesizer's sample rate to the specified value -//! (in Hz, must be positive). -//! -//! \param rate The new synthesis sample rate. -//! \throw InvalidArgument if the specified rate is nonpositive. -void -Synthesizer::setSampleRate( double rate ) -{ - // check to make sure that the specified rate - // is valid: - if ( rate <= 0. ) - { - Throw( InvalidArgument, "Synthesizer sample rate must be positive." ); - } - - m_srateHz = rate; -} - -// --------------------------------------------------------------------------- -// filter -// --------------------------------------------------------------------------- -//! Return access to the Filter used by this Synthesizer's -//! Oscillator to implement bandwidth-enhanced sinusoidal -//! synthesis. (Can use this access to make changes to the -//! filter coefficients.) -Filter & -Synthesizer::filter( void ) -{ - return m_osc.filter(); -} - -// -- parameters structure -- - -// --------------------------------------------------------------------------- -// Synthesizer::Parameters default constructor -// --------------------------------------------------------------------------- -//! Assign default initial values to the Synthesizer parameters, Filter -//! defaults are defined in Oscillator.C. - -static const double Default_FadeTime_Ms = 0.0; -static const double Default_SampleRate_Hz = 44100; -//static const Synthesizer::EnhancementFlag Default_Enhancement_Flag = Synthesizer::BwEnhanced; - - -Synthesizer::Parameters::Parameters( void ) : - fadeTime( 0.001 ), - sampleRate( Default_SampleRate_Hz ), - // enhancement( Default_Enhancement_Flag ), - filter( Oscillator::prototype_filter() ) -{ -} - -// --------------------------------------------------------------------------- -// Synthesizer default Parameters local access only -// --------------------------------------------------------------------------- - -static -Synthesizer::Parameters & TheSynthesizerDefaultParameters( void ) -{ - static Synthesizer::Parameters params; - return params; - -} - -// --------------------------------------------------------------------------- -// Synthesizer default Parameters access (static) -// --------------------------------------------------------------------------- -//! Default configuration of a Loris::Synthesizer. Modify the values -//! in this structure to alter the configuration of all Synthesizers, -//! including those used by the AiffFile class to render Partials. -const Synthesizer::Parameters & -Synthesizer::DefaultParameters( void ) -{ - return TheSynthesizerDefaultParameters(); -} - -// --------------------------------------------------------------------------- -// Synthesizer default Parameters access (static) -// --------------------------------------------------------------------------- -//! Assign a new default configuration of a Loris::Synthesizer -//! to alter the configuration of all Synthesizers, -//! including those used by the AiffFile class to render Partials. -//! -//! \param params A Parameters struct describing the new default -//! configuration for Synthesizers. -//! \throw InvalidArgument if any of the parameters is invalid. -void Synthesizer::SetDefaultParameters( const Synthesizer::Parameters & params ) -{ - if ( IsValidParameters( params ) ) - { - TheSynthesizerDefaultParameters() = params; - } -} - -// --------------------------------------------------------------------------- -// IsValidParameters (static) -// --------------------------------------------------------------------------- -//! Check the validty of a Parameters structure. Returns true if the -//! struct represents a valid Synthesizer configuration, and false otherwise. -//! -//! \param params A Parameters struct describing a configuration for -//! Synthesizers. -bool Synthesizer::IsValidParameters( const Parameters & params ) -{ - // check to make sure that the sample rate is valid: - if ( 0. >= params.sampleRate ) - { - Throw( InvalidArgument, "Synthesizer sample rate must be positive." ); - } - - // check to make sure that the specified fade time - // is valid: - if ( 0. > params.fadeTime ) - { - Throw( InvalidArgument, - "Synthesizer Partial fade time must be non-negative." ); - } - - // check that the filter coefficients are valid -- pretty much - // any coefficients are valid as long as the zeroeth feedback - // coefficient is non-zero: - if ( 0. == params.filter.denominator()[0] ) - { - Throw( InvalidArgument, - "Synthesizer filter zeroeth feedback coefficient must be non-zero." ); - } - - // if no exception has been raised, return true indicating valid params - return true; - -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/Synthesizer.h b/loris_library/Source/src/Synthesizer.h deleted file mode 100644 index e0268ba..0000000 --- a/loris_library/Source/src/Synthesizer.h +++ /dev/null @@ -1,391 +0,0 @@ -#ifndef INCLUDE_SYNTHESIZER_H -#define INCLUDE_SYNTHESIZER_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Synthesizer.h - * - * Definition of class Loris::Synthesizer, a renderer of - * bandwidth-enhanced Partials. - * - * Kelly Fitz, 16 Aug 1999 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - - - // TODO: - // Passing the sample vector in to Synthesizer no longer makes any sense, - // if the Synthesizer can (must) resize the buffer anyway, it may as well - // own it. In a future version, the Synthesizer owns a vector (need to add - // a method to clear it), and provides access to it (as it currently does). - // When this change is made, it probably makes sense to remove the function - // call operators. - - -#include "Oscillator.h" -#include "PartialList.h" -#include "PartialUtils.h" - -#include - -// begin namespace -namespace Loris { - -// --------------------------------------------------------------------------- -// class Synthesizer -// -//! A Synthesizer renders bandwidth-enhanced Partials into a buffer -//! of samples. -//! -//! Class Synthesizer represents an algorithm for rendering -//! bandwidth-enhanced Partials as floating point (double) samples at a -//! specified sampling rate, and accumulating them into a buffer. -//! -//! The Synthesizer does not own the sample buffer, the client is responsible -//! for its construction and destruction, and many Synthesizers may share -//! a buffer. -// -class Synthesizer -{ -// -- public interface -- -public: -// -- construction -- - - struct Parameters; // defined below - - //! Construct a Synthesizer using the default parameters and sample - //! buffer (a standard library vector). Since Partials generated by - //! the Loris Analyzer generally begin and end at non-zero amplitude, - //! zero-amplitude Breakpoints are inserted at either end of the Partial, - //! at a temporal distance equal to the fade time, to reduce turn-on and - //! turn-off artifacts. - //! - //! \sa Synthesizer::Parameters - //! - //! \param buffer The vector (of doubles) into which rendered samples - //! should be accumulated. - //! \throw InvalidArgument if any of the parameters is invalid. - Synthesizer( std::vector & buffer ); - - - //! Construct a Synthesizer using the specified parameters and sample - //! buffer (a standard library vector). Since Partials generated by the - //! Loris Analyzer generally begin and end at non-zero amplitude, zero-amplitude - //! Breakpoints are inserted at either end of the Partial, at a temporal - //! distance equal to the fade time, to reduce turn-on and turn-off - //! artifacts. - //! - //! \param params A Parameters struct storing the configuration of - //! Synthesizer parameters. - //! \param buffer The vector (of doubles) into which rendered samples - //! should be accumulated. - //! \throw InvalidArgument if any of the parameters is invalid. - Synthesizer( Parameters params, std::vector & buffer ); - - //! Construct a Synthesizer using the specified sampling rate, sample - //! buffer (a standard library vector), and the default fade time - //! stored in the DefaultParameters. Since Partials generated by the Loris - //! Analyzer generally begin and end at non-zero amplitude, zero-amplitude - //! Breakpoints are inserted at either end of the Partial, at a temporal - //! distance equal to the fade time, to reduce turn-on and turn-off - //! artifacts. - //! - //! \param srate The rate (Hz) at which to synthesize samples - //! (must be positive). - //! \param buffer The vector (of doubles) into which rendered samples - //! should be accumulated. - //! \throw InvalidArgument if the specfied sample rate is non-positive. - Synthesizer( double srate, std::vector & buffer ); - - //! Construct a Synthesizer using the specified sampling rate, sample - //! buffer (a standard library vector), and Partial fade time - //! (in seconds). Since Partials generated by the Loris Analyzer - //! generally begin and end at non-zero amplitude, zero-amplitude - //! Breakpoints are inserted at either end of the Partial, at a temporal - //! distance equal to the fade time, to reduce turn-on and turn-off - //! artifacts. - //! - //! \param srate The rate (Hz) at which to synthesize samples - //! (must be positive). - //! \param buffer The vector (of doubles) into which rendered samples - //! should be accumulated. - //! \param fadeTime The Partial fade time in seconds (must be non-negative). - //! \throw InvalidArgument if the specfied sample rate is non-positive. - //! \throw InvalidArgument if the specified fade time is negative. - Synthesizer( double srate, std::vector & buffer, double fadeTime ); - - // Compiler can generate copy, assign, and destroy. - // Synthesizer( const Synthesizer & other ); - // ~Synthesizer( void ); - // Synthesizer & operator= ( const Synthesizer & other ); - -// -- synthesis -- - - //! Synthesize a bandwidth-enhanced sinusoidal Partial. Zero-amplitude - //! Breakpoints are inserted at either end of the Partial to reduce - //! turn-on and turn-off artifacts, as described above. The synthesizer - //! will resize the buffer as necessary to accommodate all the samples, - //! including the fade out. Previous contents of the buffer are not - //! overwritten. Partials with start times earlier than the Partial fade - //! time will have shorter onset fades. Partials are not rendered at - //! frequencies above the half-sample rate. - //! - //! \param p The Partial to synthesize. - //! \return Nothing. - //! \pre The partial must have non-negative start time. - //! \post This Synthesizer's sample buffer (vector) has been - //! resized to accommodate the entire duration of the - //! Partial, p, including fade out at the end. - //! \throw InvalidPartial if the Partial has negative start time. - void synthesize( Partial p ); - - //! Function call operator: same as synthesize( p ). - void operator() ( const Partial & p ) { synthesize( p ) ; } - - - //! Synthesize all Partials on the specified half-open (STL-style) range. - //! Null Breakpoints are inserted at either end of the Partial to reduce - //! turn-on and turn-off artifacts, as described above. The synthesizer - //! will resize the buffer as necessary to accommodate all the samples, - //! including the fade outs. Previous contents of the buffer are not - //! overwritten. Partials with start times earlier than the Partial fade - //! time will have shorter onset fades. Partials are not rendered at - //! frequencies above the half-sample rate. - //! - //! \param begin_partials The beginning of the range of Partials - //! to synthesize. - //! \param end_partials The end of the range of Partials - //! to synthesize. - //! \return Nothing. - //! \pre The partials must have non-negative start times. - //! \post This Synthesizer's sample buffer (vector) has been - //! resized to accommodate the entire duration of all the - //! Partials including fade out at the ends. - //! \throw InvalidPartial if any Partial has negative start time. -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - void synthesize( Iter begin_partials, Iter end_partials ); -#else - inline - void synthesize( PartialList::iterator begin_partials, - PartialList::iterator end_partials ); -#endif - - //! Function call operator: same as - //! synthesize( begin_partials, end_partials ). -#if ! defined(NO_TEMPLATE_MEMBERS) - template< typename Iter > - void operator() ( Iter begin_partials, Iter end_partials ); -#else - inline - void operator() ( PartialList::iterator begin_partials, - PartialList::iterator end_partials ); -#endif - -// -- sample access -- - - //! Return a const reference to the sample buffer used (not - //! owned) by this Synthesizer. - const std::vector & samples( void ) const; - - //! Return a reference to the sample buffer used (not - //! owned) by this Synthesizer. - std::vector & samples( void ); - - -// -- parameter access and mutation -- - - - //! Return this Synthesizer's Partial fade time, in seconds. - double fadeTime( void ) const; - - //! Return the sampling rate (in Hz) for this Synthesizer. - double sampleRate( void ) const; - - //! Set this Synthesizer's fade time to the specified value - //! (in seconds, must be non-negative). - //! - //! \param partialFadeTime The new Partial fade time. - //! \throw InvalidArgument if the specified fade time is negative. - void setFadeTime( double partialFadeTime ); - - //! Set this Synthesizer's sample rate to the specified value - //! (in Hz, must be positive). - //! - //! \param rate The new synthesis sample rate. - //! \throw InvalidArgument if the specified rate is nonpositive. - void setSampleRate( double rate ); - - //! Return access to the Filter used by this Synthesizer's - //! Oscillator to implement bandwidth-enhanced sinusoidal - //! synthesis. (Can use this access to make changes to the - //! filter coefficients.) - Filter & filter( void ); - - -// -- parameters structure -- - - enum - { - Default_FadeTime_Ms = 1, - Default_SampleRate_Hz = 44100 - }; - - // enum EnhancementFlag { Sinusoidal = 0, BwEnhanced = 1 }; - - //! Structure storing a configuration of Synthesizer parameters. - //! Elements in this struct can be freely modified, the configuration - //! is validated before it can be used to construct a Synthesizer. - //! - //! \sa IsValidParameters - struct Parameters - { - double fadeTime; - double sampleRate; - // EnhancementFlag enhancement; - - Filter filter; - - // default constructor - // - //! Assign default initial values to the Synthesizer parameters, Filter - //! defaults are defined in Filter.C, others in Synthesizer.C. - Parameters( void ); - - // copy, assign, and destroy are free - }; - - //! Default configuration of a Loris::Synthesizer. Modify the values - //! in this structure to alter the configuration of all Synthesizers, - //! including those used by the AiffFile class to render Partials. - static const Parameters & DefaultParameters( void ); - - //! Assign a new default configuration of a Loris::Synthesizer - //! to alter the configuration of all Synthesizers, - //! including those used by the AiffFile class to render Partials. - //! - //! \param params A Parameters struct describing the new default - //! configuration for Synthesizers. - //! \throw InvalidArgument if params reprsents an invalid configuration. - static void SetDefaultParameters( const Parameters & params ); - - //! Check the validty of a Parameters structure. Returns true if the - //! struct represents a valid Synthesizer configuration, otherwise - //! raise InvalidArgument reporting the specific error. - //! - //! \param params A Parameters struct describing a configuration for - //! Synthesizers. - //! \throw InvalidArgument if params reprsents an invalid configuration. - static bool IsValidParameters( const Parameters & params ); - - -// -- implementation -- -private: - - Oscillator m_osc; // the Synthesizer has-a Oscillator that it uses to render - // all the Partials one by one. - - std::vector< double > * m_sampleBuffer; // samples are computed and stored here, BUT - // Synthesizer does NOT own this buffer. - - double m_fadeTimeSec; // Partial fade in/out time in seconds - double m_srateHz; // sample rate in Hz - -}; // end of class Synthesizer - - -// --------------------------------------------------------------------------- -// synthesize -// --------------------------------------------------------------------------- -//! Synthesize all Partials on the specified half-open (STL-style) range. -//! Null Breakpoints are inserted at either end of the Partial to reduce -//! turn-on and turn-off artifacts, as described above. The synthesizer -//! will resize the buffer as necessary to accommodate all the samples, -//! including the fade outs. Previous contents of the buffer are not -//! overwritten. Partials with start times earlier than the Partial fade -//! time will have shorter onset fades. -//! -//! \param begin_partials The beginning of the range of Partials -//! to synthesize. -//! \param end_partials The end of the range of Partials -//! to synthesize. -//! \return Nothing. -//! \pre The partials must have non-negative start times. -//! \post This Synthesizer's sample buffer (vector) has been -//! resized to accommodate the entire duration of all the -//! Partials including fade out at the ends. -//! \throw InvalidPartial if any Partial has negative start time. -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void -Synthesizer::synthesize( Iter begin_partials, Iter end_partials ) -#else -inline void -Synthesizer::synthesize( PartialList::iterator begin_partials, - PartialList::iterator end_partials ) -#endif -{ - // grow the sample buffer, if necessary, to accommodate the latest - // Partial, with the fade time tacked on the end - double duration = - PartialUtils::timeSpan( begin_partials, end_partials ).second + - m_fadeTimeSec; - - typedef std::vector< double >::size_type Sz_Type; - Sz_Type Nsamps = 1 + Sz_Type( duration * m_srateHz ); - if ( m_sampleBuffer->size() < Nsamps ) - { - m_sampleBuffer->resize( Nsamps ); - } - - while ( begin_partials != end_partials ) - { - synthesize( *(begin_partials++) ); - } -} - -// --------------------------------------------------------------------------- -// operator() -// --------------------------------------------------------------------------- -//! Function call operator: same as -//! synthesize( begin_partials, end_partials, timeShift ). -// -#if ! defined(NO_TEMPLATE_MEMBERS) -template -void -Synthesizer::operator() ( Iter begin_partials, Iter end_partials ) -#else -inline void -Synthesizer::operator() ( PartialList::iterator begin_partials, - PartialList::iterator end_partials ) -#endif -{ - synthesize( begin_partials, end_partials ); -} - -} // end of namespace Loris - -#endif /* ndef INCLUDE_SYNTHESIZER_H */ diff --git a/loris_library/Source/src/fftsg.cpp b/loris_library/Source/src/fftsg.cpp deleted file mode 100644 index dc3e237..0000000 --- a/loris_library/Source/src/fftsg.cpp +++ /dev/null @@ -1,3331 +0,0 @@ -/* - double-precision floating point transform functions - adapted from the tranform library of Ooura. - http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html - - Identical to fftsg.c, wrapped in extern "C" - to prevent name-mangling by a C++ compiler. - - Kelly Fitz 21 July 2006 - kfitz@cerlsoundgroup.org -*/ -/* -Fast Fourier/Cosine/Sine Transform - dimension :one - data length :power of 2 - decimation :frequency - radix :split-radix - data :inplace - table :use -functions - cdft: Complex Discrete Fourier Transform - rdft: Real Discrete Fourier Transform - ddct: Discrete Cosine Transform - ddst: Discrete Sine Transform - dfct: Cosine Transform of RDFT (Real Symmetric DFT) - dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) -function prototypes - void cdft(int, int, double *, int *, double *); - void rdft(int, int, double *, int *, double *); - void ddct(int, int, double *, int *, double *); - void ddst(int, int, double *, int *, double *); - void dfct(int, double *, double *, int *, double *); - void dfst(int, double *, double *, int *, double *); -macro definitions - USE_CDFT_PTHREADS : default=not defined - CDFT_THREADS_BEGIN_N : must be >= 512, default=8192 - CDFT_4THREADS_BEGIN_N : must be >= 512, default=65536 - USE_CDFT_WINTHREADS : default=not defined - CDFT_THREADS_BEGIN_N : must be >= 512, default=32768 - CDFT_4THREADS_BEGIN_N : must be >= 512, default=524288 - - --------- Complex DFT (Discrete Fourier Transform) -------- - [definition] - - X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k - X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k - ip[0] = 0; // first time only - cdft(2*n, 1, a, ip, w); - - ip[0] = 0; // first time only - cdft(2*n, -1, a, ip, w); - [parameters] - 2*n :data length (int) - n >= 1, n = power of 2 - a[0...2*n-1] :input/output data (double *) - input data - a[2*j] = Re(x[j]), - a[2*j+1] = Im(x[j]), 0<=j= 2+sqrt(n) - strictly, - length of ip >= - 2+(1<<(int)(log(n+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n/2-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - cdft(2*n, -1, a, ip, w); - is - cdft(2*n, 1, a, ip, w); - for (j = 0; j <= 2 * n - 1; j++) { - a[j] *= 1.0 / n; - } - . - - --------- Real DFT / Inverse of Real DFT -------- - [definition] - RDFT - R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 - I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) - a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + - sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + - sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k - ip[0] = 0; // first time only - rdft(n, 1, a, ip, w); - - ip[0] = 0; // first time only - rdft(n, -1, a, ip, w); - [parameters] - n :data length (int) - n >= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - - output data - a[2*k] = R[k], 0<=k - input data - a[2*j] = R[j], 0<=j= 2+sqrt(n/2) - strictly, - length of ip >= - 2+(1<<(int)(log(n/2+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n/2-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - rdft(n, 1, a, ip, w); - is - rdft(n, -1, a, ip, w); - for (j = 0; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - --------- DCT (Discrete Cosine Transform) / Inverse of DCT -------- - [definition] - IDCT (excluding scale) - C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT - C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k - ip[0] = 0; // first time only - ddct(n, 1, a, ip, w); - - ip[0] = 0; // first time only - ddct(n, -1, a, ip, w); - [parameters] - n :data length (int) - n >= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - output data - a[k] = C[k], 0<=k= 2+sqrt(n/2) - strictly, - length of ip >= - 2+(1<<(int)(log(n/2+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/4-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - ddct(n, -1, a, ip, w); - is - a[0] *= 0.5; - ddct(n, 1, a, ip, w); - for (j = 0; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - --------- DST (Discrete Sine Transform) / Inverse of DST -------- - [definition] - IDST (excluding scale) - S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST - S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 - ip[0] = 0; // first time only - ddst(n, 1, a, ip, w); - - ip[0] = 0; // first time only - ddst(n, -1, a, ip, w); - [parameters] - n :data length (int) - n >= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - - input data - a[j] = A[j], 0 - output data - a[k] = S[k], 0= 2+sqrt(n/2) - strictly, - length of ip >= - 2+(1<<(int)(log(n/2+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/4-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - ddst(n, -1, a, ip, w); - is - a[0] *= 0.5; - ddst(n, 1, a, ip, w); - for (j = 0; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - --------- Cosine Transform of RDFT (Real Symmetric DFT) -------- - [definition] - C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n - [usage] - ip[0] = 0; // first time only - dfct(n, a, t, ip, w); - [parameters] - n :data length - 1 (int) - n >= 2, n = power of 2 - a[0...n] :input/output data (double *) - output data - a[k] = C[k], 0<=k<=n - t[0...n/2] :work area (double *) - ip[0...*] :work area for bit reversal (int *) - length of ip >= 2+sqrt(n/4) - strictly, - length of ip >= - 2+(1<<(int)(log(n/4+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/8-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - a[0] *= 0.5; - a[n] *= 0.5; - dfct(n, a, t, ip, w); - is - a[0] *= 0.5; - a[n] *= 0.5; - dfct(n, a, t, ip, w); - for (j = 0; j <= n; j++) { - a[j] *= 2.0 / n; - } - . - - --------- Sine Transform of RDFT (Real Anti-symmetric DFT) -------- - [definition] - S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - output data - a[k] = S[k], 0= 2+sqrt(n/4) - strictly, - length of ip >= - 2+(1<<(int)(log(n/4+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/8-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - dfst(n, a, t, ip, w); - is - dfst(n, a, t, ip, w); - for (j = 1; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - -Appendix : - The cos/sin table is recalculated when the larger table required. - w[] and ip[] are compatible with all routines. -*/ - -#if defined(__cplusplus) -extern "C" { -#endif - -void cdft(int n, int isgn, double *a, int *ip, double *w) -{ - void makewt(int nw, int *ip, double *w); - void cftfsub(int n, double *a, int *ip, int nw, double *w); - void cftbsub(int n, double *a, int *ip, int nw, double *w); - int nw; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - if (isgn >= 0) { - cftfsub(n, a, ip, nw, w); - } else { - cftbsub(n, a, ip, nw, w); - } -} - - -void rdft(int n, int isgn, double *a, int *ip, double *w) -{ - void makewt(int nw, int *ip, double *w); - void makect(int nc, int *ip, double *c); - void cftfsub(int n, double *a, int *ip, int nw, double *w); - void cftbsub(int n, double *a, int *ip, int nw, double *w); - void rftfsub(int n, double *a, int nc, double *c); - void rftbsub(int n, double *a, int nc, double *c); - int nw, nc; - double xi; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > (nc << 2)) { - nc = n >> 2; - makect(nc, ip, w + nw); - } - if (isgn >= 0) { - if (n > 4) { - cftfsub(n, a, ip, nw, w); - rftfsub(n, a, nc, w + nw); - } else if (n == 4) { - cftfsub(n, a, ip, nw, w); - } - xi = a[0] - a[1]; - a[0] += a[1]; - a[1] = xi; - } else { - a[1] = 0.5 * (a[0] - a[1]); - a[0] -= a[1]; - if (n > 4) { - rftbsub(n, a, nc, w + nw); - cftbsub(n, a, ip, nw, w); - } else if (n == 4) { - cftbsub(n, a, ip, nw, w); - } - } -} - - -void ddct(int n, int isgn, double *a, int *ip, double *w) -{ - void makewt(int nw, int *ip, double *w); - void makect(int nc, int *ip, double *c); - void cftfsub(int n, double *a, int *ip, int nw, double *w); - void cftbsub(int n, double *a, int *ip, int nw, double *w); - void rftfsub(int n, double *a, int nc, double *c); - void rftbsub(int n, double *a, int nc, double *c); - void dctsub(int n, double *a, int nc, double *c); - int j, nw, nc; - double xr; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > nc) { - nc = n; - makect(nc, ip, w + nw); - } - if (isgn < 0) { - xr = a[n - 1]; - for (j = n - 2; j >= 2; j -= 2) { - a[j + 1] = a[j] - a[j - 1]; - a[j] += a[j - 1]; - } - a[1] = a[0] - xr; - a[0] += xr; - if (n > 4) { - rftbsub(n, a, nc, w + nw); - cftbsub(n, a, ip, nw, w); - } else if (n == 4) { - cftbsub(n, a, ip, nw, w); - } - } - dctsub(n, a, nc, w + nw); - if (isgn >= 0) { - if (n > 4) { - cftfsub(n, a, ip, nw, w); - rftfsub(n, a, nc, w + nw); - } else if (n == 4) { - cftfsub(n, a, ip, nw, w); - } - xr = a[0] - a[1]; - a[0] += a[1]; - for (j = 2; j < n; j += 2) { - a[j - 1] = a[j] - a[j + 1]; - a[j] += a[j + 1]; - } - a[n - 1] = xr; - } -} - - -void ddst(int n, int isgn, double *a, int *ip, double *w) -{ - void makewt(int nw, int *ip, double *w); - void makect(int nc, int *ip, double *c); - void cftfsub(int n, double *a, int *ip, int nw, double *w); - void cftbsub(int n, double *a, int *ip, int nw, double *w); - void rftfsub(int n, double *a, int nc, double *c); - void rftbsub(int n, double *a, int nc, double *c); - void dstsub(int n, double *a, int nc, double *c); - int j, nw, nc; - double xr; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > nc) { - nc = n; - makect(nc, ip, w + nw); - } - if (isgn < 0) { - xr = a[n - 1]; - for (j = n - 2; j >= 2; j -= 2) { - a[j + 1] = -a[j] - a[j - 1]; - a[j] -= a[j - 1]; - } - a[1] = a[0] + xr; - a[0] -= xr; - if (n > 4) { - rftbsub(n, a, nc, w + nw); - cftbsub(n, a, ip, nw, w); - } else if (n == 4) { - cftbsub(n, a, ip, nw, w); - } - } - dstsub(n, a, nc, w + nw); - if (isgn >= 0) { - if (n > 4) { - cftfsub(n, a, ip, nw, w); - rftfsub(n, a, nc, w + nw); - } else if (n == 4) { - cftfsub(n, a, ip, nw, w); - } - xr = a[0] - a[1]; - a[0] += a[1]; - for (j = 2; j < n; j += 2) { - a[j - 1] = -a[j] - a[j + 1]; - a[j] -= a[j + 1]; - } - a[n - 1] = -xr; - } -} - - -void dfct(int n, double *a, double *t, int *ip, double *w) -{ - void makewt(int nw, int *ip, double *w); - void makect(int nc, int *ip, double *c); - void cftfsub(int n, double *a, int *ip, int nw, double *w); - void rftfsub(int n, double *a, int nc, double *c); - void dctsub(int n, double *a, int nc, double *c); - int j, k, l, m, mh, nw, nc; - double xr, xi, yr, yi; - - nw = ip[0]; - if (n > (nw << 3)) { - nw = n >> 3; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > (nc << 1)) { - nc = n >> 1; - makect(nc, ip, w + nw); - } - m = n >> 1; - yi = a[m]; - xi = a[0] + a[n]; - a[0] -= a[n]; - t[0] = xi - yi; - t[m] = xi + yi; - if (n > 2) { - mh = m >> 1; - for (j = 1; j < mh; j++) { - k = m - j; - xr = a[j] - a[n - j]; - xi = a[j] + a[n - j]; - yr = a[k] - a[n - k]; - yi = a[k] + a[n - k]; - a[j] = xr; - a[k] = yr; - t[j] = xi - yi; - t[k] = xi + yi; - } - t[mh] = a[mh] + a[n - mh]; - a[mh] -= a[n - mh]; - dctsub(m, a, nc, w + nw); - if (m > 4) { - cftfsub(m, a, ip, nw, w); - rftfsub(m, a, nc, w + nw); - } else if (m == 4) { - cftfsub(m, a, ip, nw, w); - } - a[n - 1] = a[0] - a[1]; - a[1] = a[0] + a[1]; - for (j = m - 2; j >= 2; j -= 2) { - a[2 * j + 1] = a[j] + a[j + 1]; - a[2 * j - 1] = a[j] - a[j + 1]; - } - l = 2; - m = mh; - while (m >= 2) { - dctsub(m, t, nc, w + nw); - if (m > 4) { - cftfsub(m, t, ip, nw, w); - rftfsub(m, t, nc, w + nw); - } else if (m == 4) { - cftfsub(m, t, ip, nw, w); - } - a[n - l] = t[0] - t[1]; - a[l] = t[0] + t[1]; - k = 0; - for (j = 2; j < m; j += 2) { - k += l << 2; - a[k - l] = t[j] - t[j + 1]; - a[k + l] = t[j] + t[j + 1]; - } - l <<= 1; - mh = m >> 1; - for (j = 0; j < mh; j++) { - k = m - j; - t[j] = t[m + k] - t[m + j]; - t[k] = t[m + k] + t[m + j]; - } - t[mh] = t[m + mh]; - m = mh; - } - a[l] = t[0]; - a[n] = t[2] - t[1]; - a[0] = t[2] + t[1]; - } else { - a[1] = a[0]; - a[2] = t[0]; - a[0] = t[1]; - } -} - - -void dfst(int n, double *a, double *t, int *ip, double *w) -{ - void makewt(int nw, int *ip, double *w); - void makect(int nc, int *ip, double *c); - void cftfsub(int n, double *a, int *ip, int nw, double *w); - void rftfsub(int n, double *a, int nc, double *c); - void dstsub(int n, double *a, int nc, double *c); - int j, k, l, m, mh, nw, nc; - double xr, xi, yr, yi; - - nw = ip[0]; - if (n > (nw << 3)) { - nw = n >> 3; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > (nc << 1)) { - nc = n >> 1; - makect(nc, ip, w + nw); - } - if (n > 2) { - m = n >> 1; - mh = m >> 1; - for (j = 1; j < mh; j++) { - k = m - j; - xr = a[j] + a[n - j]; - xi = a[j] - a[n - j]; - yr = a[k] + a[n - k]; - yi = a[k] - a[n - k]; - a[j] = xr; - a[k] = yr; - t[j] = xi + yi; - t[k] = xi - yi; - } - t[0] = a[mh] - a[n - mh]; - a[mh] += a[n - mh]; - a[0] = a[m]; - dstsub(m, a, nc, w + nw); - if (m > 4) { - cftfsub(m, a, ip, nw, w); - rftfsub(m, a, nc, w + nw); - } else if (m == 4) { - cftfsub(m, a, ip, nw, w); - } - a[n - 1] = a[1] - a[0]; - a[1] = a[0] + a[1]; - for (j = m - 2; j >= 2; j -= 2) { - a[2 * j + 1] = a[j] - a[j + 1]; - a[2 * j - 1] = -a[j] - a[j + 1]; - } - l = 2; - m = mh; - while (m >= 2) { - dstsub(m, t, nc, w + nw); - if (m > 4) { - cftfsub(m, t, ip, nw, w); - rftfsub(m, t, nc, w + nw); - } else if (m == 4) { - cftfsub(m, t, ip, nw, w); - } - a[n - l] = t[1] - t[0]; - a[l] = t[0] + t[1]; - k = 0; - for (j = 2; j < m; j += 2) { - k += l << 2; - a[k - l] = -t[j] - t[j + 1]; - a[k + l] = t[j] - t[j + 1]; - } - l <<= 1; - mh = m >> 1; - for (j = 1; j < mh; j++) { - k = m - j; - t[j] = t[m + k] + t[m + j]; - t[k] = t[m + k] - t[m + j]; - } - t[0] = t[m + mh]; - m = mh; - } - a[l] = t[0]; - } - a[0] = 0; -} - - -/* -------- initializing routines -------- */ - - -#include - -void makewt(int nw, int *ip, double *w) -{ - void makeipt(int nw, int *ip); - int j, nwh, nw0, nw1; - double delta, wn4r, wk1r, wk1i, wk3r, wk3i; - - ip[0] = nw; - ip[1] = 1; - if (nw > 2) { - nwh = nw >> 1; - delta = atan(1.0) / nwh; - wn4r = cos(delta * nwh); - w[0] = 1; - w[1] = wn4r; - if (nwh == 4) { - w[2] = cos(delta * 2); - w[3] = sin(delta * 2); - } else if (nwh > 4) { - makeipt(nw, ip); - w[2] = 0.5 / cos(delta * 2); - w[3] = 0.5 / cos(delta * 6); - for (j = 4; j < nwh; j += 4) { - w[j] = cos(delta * j); - w[j + 1] = sin(delta * j); - w[j + 2] = cos(3 * delta * j); - w[j + 3] = -sin(3 * delta * j); - } - } - nw0 = 0; - while (nwh > 2) { - nw1 = nw0 + nwh; - nwh >>= 1; - w[nw1] = 1; - w[nw1 + 1] = wn4r; - if (nwh == 4) { - wk1r = w[nw0 + 4]; - wk1i = w[nw0 + 5]; - w[nw1 + 2] = wk1r; - w[nw1 + 3] = wk1i; - } else if (nwh > 4) { - wk1r = w[nw0 + 4]; - wk3r = w[nw0 + 6]; - w[nw1 + 2] = 0.5 / wk1r; - w[nw1 + 3] = 0.5 / wk3r; - for (j = 4; j < nwh; j += 4) { - wk1r = w[nw0 + 2 * j]; - wk1i = w[nw0 + 2 * j + 1]; - wk3r = w[nw0 + 2 * j + 2]; - wk3i = w[nw0 + 2 * j + 3]; - w[nw1 + j] = wk1r; - w[nw1 + j + 1] = wk1i; - w[nw1 + j + 2] = wk3r; - w[nw1 + j + 3] = wk3i; - } - } - nw0 = nw1; - } - } -} - - -void makeipt(int nw, int *ip) -{ - int j, l, m, m2, p, q; - - ip[2] = 0; - ip[3] = 16; - m = 2; - for (l = nw; l > 32; l >>= 2) { - m2 = m << 1; - q = m2 << 3; - for (j = m; j < m2; j++) { - p = ip[j] << 2; - ip[m + j] = p; - ip[m2 + j] = p + q; - } - m = m2; - } -} - - -void makect(int nc, int *ip, double *c) -{ - int j, nch; - double delta; - - ip[1] = nc; - if (nc > 1) { - nch = nc >> 1; - delta = atan(1.0) / nch; - c[0] = cos(delta * nch); - c[nch] = 0.5 * c[0]; - for (j = 1; j < nch; j++) { - c[j] = 0.5 * cos(delta * j); - c[nc - j] = 0.5 * sin(delta * j); - } - } -} - - -/* -------- child routines -------- */ - - -#ifdef USE_CDFT_PTHREADS -#define USE_CDFT_THREADS -#ifndef CDFT_THREADS_BEGIN_N -#define CDFT_THREADS_BEGIN_N 8192 -#endif -#ifndef CDFT_4THREADS_BEGIN_N -#define CDFT_4THREADS_BEGIN_N 65536 -#endif -#include -#include -#include -#define cdft_thread_t pthread_t -#define cdft_thread_create(thp,func,argp) { \ - if (pthread_create(thp, NULL, func, (void *) argp) != 0) { \ - fprintf(stderr, "cdft thread error\n"); \ - exit(1); \ - } \ -} -#define cdft_thread_wait(th) { \ - if (pthread_join(th, NULL) != 0) { \ - fprintf(stderr, "cdft thread error\n"); \ - exit(1); \ - } \ -} -#endif /* USE_CDFT_PTHREADS */ - - -#ifdef USE_CDFT_WINTHREADS -#define USE_CDFT_THREADS -#ifndef CDFT_THREADS_BEGIN_N -#define CDFT_THREADS_BEGIN_N 32768 -#endif -#ifndef CDFT_4THREADS_BEGIN_N -#define CDFT_4THREADS_BEGIN_N 524288 -#endif -#include -#include -#include -#define cdft_thread_t HANDLE -#define cdft_thread_create(thp,func,argp) { \ - DWORD thid; \ - *(thp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) func, (LPVOID) argp, 0, &thid); \ - if (*(thp) == 0) { \ - fprintf(stderr, "cdft thread error\n"); \ - exit(1); \ - } \ -} -#define cdft_thread_wait(th) { \ - WaitForSingleObject(th, INFINITE); \ - CloseHandle(th); \ -} -#endif /* USE_CDFT_WINTHREADS */ - - -void cftfsub(int n, double *a, int *ip, int nw, double *w) -{ - void bitrv2(int n, int *ip, double *a); - void bitrv216(double *a); - void bitrv208(double *a); - void cftf1st(int n, double *a, double *w); - void cftrec4(int n, double *a, int nw, double *w); - void cftleaf(int n, int isplt, double *a, int nw, double *w); - void cftfx41(int n, double *a, int nw, double *w); - void cftf161(double *a, double *w); - void cftf081(double *a, double *w); - void cftf040(double *a); - void cftx020(double *a); -#ifdef USE_CDFT_THREADS - void cftrec4_th(int n, double *a, int nw, double *w); -#endif /* USE_CDFT_THREADS */ - - if (n > 8) { - if (n > 32) { - cftf1st(n, a, &w[nw - (n >> 2)]); -#ifdef USE_CDFT_THREADS - if (n > CDFT_THREADS_BEGIN_N) { - cftrec4_th(n, a, nw, w); - } else -#endif /* USE_CDFT_THREADS */ - if (n > 512) { - cftrec4(n, a, nw, w); - } else if (n > 128) { - cftleaf(n, 1, a, nw, w); - } else { - cftfx41(n, a, nw, w); - } - bitrv2(n, ip, a); - } else if (n == 32) { - cftf161(a, &w[nw - 8]); - bitrv216(a); - } else { - cftf081(a, w); - bitrv208(a); - } - } else if (n == 8) { - cftf040(a); - } else if (n == 4) { - cftx020(a); - } -} - - -void cftbsub(int n, double *a, int *ip, int nw, double *w) -{ - void bitrv2conj(int n, int *ip, double *a); - void bitrv216neg(double *a); - void bitrv208neg(double *a); - void cftb1st(int n, double *a, double *w); - void cftrec4(int n, double *a, int nw, double *w); - void cftleaf(int n, int isplt, double *a, int nw, double *w); - void cftfx41(int n, double *a, int nw, double *w); - void cftf161(double *a, double *w); - void cftf081(double *a, double *w); - void cftb040(double *a); - void cftx020(double *a); -#ifdef USE_CDFT_THREADS - void cftrec4_th(int n, double *a, int nw, double *w); -#endif /* USE_CDFT_THREADS */ - - if (n > 8) { - if (n > 32) { - cftb1st(n, a, &w[nw - (n >> 2)]); -#ifdef USE_CDFT_THREADS - if (n > CDFT_THREADS_BEGIN_N) { - cftrec4_th(n, a, nw, w); - } else -#endif /* USE_CDFT_THREADS */ - if (n > 512) { - cftrec4(n, a, nw, w); - } else if (n > 128) { - cftleaf(n, 1, a, nw, w); - } else { - cftfx41(n, a, nw, w); - } - bitrv2conj(n, ip, a); - } else if (n == 32) { - cftf161(a, &w[nw - 8]); - bitrv216neg(a); - } else { - cftf081(a, w); - bitrv208neg(a); - } - } else if (n == 8) { - cftb040(a); - } else if (n == 4) { - cftx020(a); - } -} - - -void bitrv2(int n, int *ip, double *a) -{ - int j, j1, k, k1, l, m, nh, nm; - double xr, xi, yr, yi; - - m = 1; - for (l = n >> 2; l > 8; l >>= 2) { - m <<= 1; - } - nh = n >> 1; - nm = 4 * m; - if (l == 8) { - for (k = 0; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 4 * j + 2 * ip[m + k]; - k1 = 4 * k + 2 * ip[m + j]; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += 2 * nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 -= nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += 2 * nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh; - k1 += 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= 2 * nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 += nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= 2 * nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += 2; - k1 += nh; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += 2 * nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 -= nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += 2 * nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh; - k1 -= 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= 2 * nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 += nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= 2 * nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - k1 = 4 * k + 2 * ip[m + k]; - j1 = k1 + 2; - k1 += nh; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += 2 * nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 -= nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= 2; - k1 -= nh; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh + 2; - k1 += nh + 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh - nm; - k1 += 2 * nm - 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - } else { - for (k = 0; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 4 * j + ip[m + k]; - k1 = 4 * k + ip[m + j]; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh; - k1 += 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += 2; - k1 += nh; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh; - k1 -= 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - k1 = 4 * k + ip[m + k]; - j1 = k1 + 2; - k1 += nh; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += nm; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - } -} - - -void bitrv2conj(int n, int *ip, double *a) -{ - int j, j1, k, k1, l, m, nh, nm; - double xr, xi, yr, yi; - - m = 1; - for (l = n >> 2; l > 8; l >>= 2) { - m <<= 1; - } - nh = n >> 1; - nm = 4 * m; - if (l == 8) { - for (k = 0; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 4 * j + 2 * ip[m + k]; - k1 = 4 * k + 2 * ip[m + j]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += 2 * nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 -= nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += 2 * nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh; - k1 += 2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= 2 * nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 += nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= 2 * nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += 2; - k1 += nh; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += 2 * nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 -= nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += 2 * nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh; - k1 -= 2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= 2 * nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 += nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= 2 * nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - k1 = 4 * k + 2 * ip[m + k]; - j1 = k1 + 2; - k1 += nh; - a[j1 - 1] = -a[j1 - 1]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - a[k1 + 3] = -a[k1 + 3]; - j1 += nm; - k1 += 2 * nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 -= nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= 2; - k1 -= nh; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh + 2; - k1 += nh + 2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh - nm; - k1 += 2 * nm - 2; - a[j1 - 1] = -a[j1 - 1]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - a[k1 + 3] = -a[k1 + 3]; - } - } else { - for (k = 0; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 4 * j + ip[m + k]; - k1 = 4 * k + ip[m + j]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh; - k1 += 2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += 2; - k1 += nh; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nm; - k1 += nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh; - k1 -= 2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nm; - k1 -= nm; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - k1 = 4 * k + ip[m + k]; - j1 = k1 + 2; - k1 += nh; - a[j1 - 1] = -a[j1 - 1]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - a[k1 + 3] = -a[k1 + 3]; - j1 += nm; - k1 += nm; - a[j1 - 1] = -a[j1 - 1]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - a[k1 + 3] = -a[k1 + 3]; - } - } -} - - -void bitrv216(double *a) -{ - double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, - x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, - x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; - - x1r = a[2]; - x1i = a[3]; - x2r = a[4]; - x2i = a[5]; - x3r = a[6]; - x3i = a[7]; - x4r = a[8]; - x4i = a[9]; - x5r = a[10]; - x5i = a[11]; - x7r = a[14]; - x7i = a[15]; - x8r = a[16]; - x8i = a[17]; - x10r = a[20]; - x10i = a[21]; - x11r = a[22]; - x11i = a[23]; - x12r = a[24]; - x12i = a[25]; - x13r = a[26]; - x13i = a[27]; - x14r = a[28]; - x14i = a[29]; - a[2] = x8r; - a[3] = x8i; - a[4] = x4r; - a[5] = x4i; - a[6] = x12r; - a[7] = x12i; - a[8] = x2r; - a[9] = x2i; - a[10] = x10r; - a[11] = x10i; - a[14] = x14r; - a[15] = x14i; - a[16] = x1r; - a[17] = x1i; - a[20] = x5r; - a[21] = x5i; - a[22] = x13r; - a[23] = x13i; - a[24] = x3r; - a[25] = x3i; - a[26] = x11r; - a[27] = x11i; - a[28] = x7r; - a[29] = x7i; -} - - -void bitrv216neg(double *a) -{ - double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, - x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, - x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, - x13r, x13i, x14r, x14i, x15r, x15i; - - x1r = a[2]; - x1i = a[3]; - x2r = a[4]; - x2i = a[5]; - x3r = a[6]; - x3i = a[7]; - x4r = a[8]; - x4i = a[9]; - x5r = a[10]; - x5i = a[11]; - x6r = a[12]; - x6i = a[13]; - x7r = a[14]; - x7i = a[15]; - x8r = a[16]; - x8i = a[17]; - x9r = a[18]; - x9i = a[19]; - x10r = a[20]; - x10i = a[21]; - x11r = a[22]; - x11i = a[23]; - x12r = a[24]; - x12i = a[25]; - x13r = a[26]; - x13i = a[27]; - x14r = a[28]; - x14i = a[29]; - x15r = a[30]; - x15i = a[31]; - a[2] = x15r; - a[3] = x15i; - a[4] = x7r; - a[5] = x7i; - a[6] = x11r; - a[7] = x11i; - a[8] = x3r; - a[9] = x3i; - a[10] = x13r; - a[11] = x13i; - a[12] = x5r; - a[13] = x5i; - a[14] = x9r; - a[15] = x9i; - a[16] = x1r; - a[17] = x1i; - a[18] = x14r; - a[19] = x14i; - a[20] = x6r; - a[21] = x6i; - a[22] = x10r; - a[23] = x10i; - a[24] = x2r; - a[25] = x2i; - a[26] = x12r; - a[27] = x12i; - a[28] = x4r; - a[29] = x4i; - a[30] = x8r; - a[31] = x8i; -} - - -void bitrv208(double *a) -{ - double x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; - - x1r = a[2]; - x1i = a[3]; - x3r = a[6]; - x3i = a[7]; - x4r = a[8]; - x4i = a[9]; - x6r = a[12]; - x6i = a[13]; - a[2] = x4r; - a[3] = x4i; - a[6] = x6r; - a[7] = x6i; - a[8] = x1r; - a[9] = x1i; - a[12] = x3r; - a[13] = x3i; -} - - -void bitrv208neg(double *a) -{ - double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, - x5r, x5i, x6r, x6i, x7r, x7i; - - x1r = a[2]; - x1i = a[3]; - x2r = a[4]; - x2i = a[5]; - x3r = a[6]; - x3i = a[7]; - x4r = a[8]; - x4i = a[9]; - x5r = a[10]; - x5i = a[11]; - x6r = a[12]; - x6i = a[13]; - x7r = a[14]; - x7i = a[15]; - a[2] = x7r; - a[3] = x7i; - a[4] = x3r; - a[5] = x3i; - a[6] = x5r; - a[7] = x5i; - a[8] = x1r; - a[9] = x1i; - a[10] = x6r; - a[11] = x6i; - a[12] = x2r; - a[13] = x2i; - a[14] = x4r; - a[15] = x4i; -} - - -void cftf1st(int n, double *a, double *w) -{ - int j, j0, j1, j2, j3, k, m, mh; - double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, - wd1r, wd1i, wd3r, wd3i; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, - y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; - - mh = n >> 3; - m = 2 * mh; - j1 = m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[0] + a[j2]; - x0i = a[1] + a[j2 + 1]; - x1r = a[0] - a[j2]; - x1i = a[1] - a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - a[j2] = x1r - x3i; - a[j2 + 1] = x1i + x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i - x3r; - wn4r = w[1]; - csc1 = w[2]; - csc3 = w[3]; - wd1r = 1; - wd1i = 0; - wd3r = 1; - wd3i = 0; - k = 0; - for (j = 2; j < mh - 2; j += 4) { - k += 4; - wk1r = csc1 * (wd1r + w[k]); - wk1i = csc1 * (wd1i + w[k + 1]); - wk3r = csc3 * (wd3r + w[k + 2]); - wk3i = csc3 * (wd3i + w[k + 3]); - wd1r = w[k]; - wd1i = w[k + 1]; - wd3r = w[k + 2]; - wd3i = w[k + 3]; - j1 = j + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j] + a[j2]; - x0i = a[j + 1] + a[j2 + 1]; - x1r = a[j] - a[j2]; - x1i = a[j + 1] - a[j2 + 1]; - y0r = a[j + 2] + a[j2 + 2]; - y0i = a[j + 3] + a[j2 + 3]; - y1r = a[j + 2] - a[j2 + 2]; - y1i = a[j + 3] - a[j2 + 3]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - y2r = a[j1 + 2] + a[j3 + 2]; - y2i = a[j1 + 3] + a[j3 + 3]; - y3r = a[j1 + 2] - a[j3 + 2]; - y3i = a[j1 + 3] - a[j3 + 3]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j + 2] = y0r + y2r; - a[j + 3] = y0i + y2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - a[j1 + 2] = y0r - y2r; - a[j1 + 3] = y0i - y2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2] = wk1r * x0r - wk1i * x0i; - a[j2 + 1] = wk1r * x0i + wk1i * x0r; - x0r = y1r - y3i; - x0i = y1i + y3r; - a[j2 + 2] = wd1r * x0r - wd1i * x0i; - a[j2 + 3] = wd1r * x0i + wd1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = wk3r * x0r + wk3i * x0i; - a[j3 + 1] = wk3r * x0i - wk3i * x0r; - x0r = y1r + y3i; - x0i = y1i - y3r; - a[j3 + 2] = wd3r * x0r + wd3i * x0i; - a[j3 + 3] = wd3r * x0i - wd3i * x0r; - j0 = m - j; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0] + a[j2]; - x0i = a[j0 + 1] + a[j2 + 1]; - x1r = a[j0] - a[j2]; - x1i = a[j0 + 1] - a[j2 + 1]; - y0r = a[j0 - 2] + a[j2 - 2]; - y0i = a[j0 - 1] + a[j2 - 1]; - y1r = a[j0 - 2] - a[j2 - 2]; - y1i = a[j0 - 1] - a[j2 - 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - y2r = a[j1 - 2] + a[j3 - 2]; - y2i = a[j1 - 1] + a[j3 - 1]; - y3r = a[j1 - 2] - a[j3 - 2]; - y3i = a[j1 - 1] - a[j3 - 1]; - a[j0] = x0r + x2r; - a[j0 + 1] = x0i + x2i; - a[j0 - 2] = y0r + y2r; - a[j0 - 1] = y0i + y2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - a[j1 - 2] = y0r - y2r; - a[j1 - 1] = y0i - y2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2] = wk1i * x0r - wk1r * x0i; - a[j2 + 1] = wk1i * x0i + wk1r * x0r; - x0r = y1r - y3i; - x0i = y1i + y3r; - a[j2 - 2] = wd1i * x0r - wd1r * x0i; - a[j2 - 1] = wd1i * x0i + wd1r * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = wk3i * x0r + wk3r * x0i; - a[j3 + 1] = wk3i * x0i - wk3r * x0r; - x0r = y1r + y3i; - x0i = y1i - y3r; - a[j3 - 2] = wd3i * x0r + wd3r * x0i; - a[j3 - 1] = wd3i * x0i - wd3r * x0r; - } - wk1r = csc1 * (wd1r + wn4r); - wk1i = csc1 * (wd1i + wn4r); - wk3r = csc3 * (wd3r - wn4r); - wk3i = csc3 * (wd3i - wn4r); - j0 = mh; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0 - 2] + a[j2 - 2]; - x0i = a[j0 - 1] + a[j2 - 1]; - x1r = a[j0 - 2] - a[j2 - 2]; - x1i = a[j0 - 1] - a[j2 - 1]; - x2r = a[j1 - 2] + a[j3 - 2]; - x2i = a[j1 - 1] + a[j3 - 1]; - x3r = a[j1 - 2] - a[j3 - 2]; - x3i = a[j1 - 1] - a[j3 - 1]; - a[j0 - 2] = x0r + x2r; - a[j0 - 1] = x0i + x2i; - a[j1 - 2] = x0r - x2r; - a[j1 - 1] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2 - 2] = wk1r * x0r - wk1i * x0i; - a[j2 - 1] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3 - 2] = wk3r * x0r + wk3i * x0i; - a[j3 - 1] = wk3r * x0i - wk3i * x0r; - x0r = a[j0] + a[j2]; - x0i = a[j0 + 1] + a[j2 + 1]; - x1r = a[j0] - a[j2]; - x1i = a[j0 + 1] - a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j0] = x0r + x2r; - a[j0 + 1] = x0i + x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2] = wn4r * (x0r - x0i); - a[j2 + 1] = wn4r * (x0i + x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = -wn4r * (x0r + x0i); - a[j3 + 1] = -wn4r * (x0i - x0r); - x0r = a[j0 + 2] + a[j2 + 2]; - x0i = a[j0 + 3] + a[j2 + 3]; - x1r = a[j0 + 2] - a[j2 + 2]; - x1i = a[j0 + 3] - a[j2 + 3]; - x2r = a[j1 + 2] + a[j3 + 2]; - x2i = a[j1 + 3] + a[j3 + 3]; - x3r = a[j1 + 2] - a[j3 + 2]; - x3i = a[j1 + 3] - a[j3 + 3]; - a[j0 + 2] = x0r + x2r; - a[j0 + 3] = x0i + x2i; - a[j1 + 2] = x0r - x2r; - a[j1 + 3] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2 + 2] = wk1i * x0r - wk1r * x0i; - a[j2 + 3] = wk1i * x0i + wk1r * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3 + 2] = wk3i * x0r + wk3r * x0i; - a[j3 + 3] = wk3i * x0i - wk3r * x0r; -} - - -void cftb1st(int n, double *a, double *w) -{ - int j, j0, j1, j2, j3, k, m, mh; - double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, - wd1r, wd1i, wd3r, wd3i; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, - y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; - - mh = n >> 3; - m = 2 * mh; - j1 = m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[0] + a[j2]; - x0i = -a[1] - a[j2 + 1]; - x1r = a[0] - a[j2]; - x1i = -a[1] + a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[0] = x0r + x2r; - a[1] = x0i - x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i + x2i; - a[j2] = x1r + x3i; - a[j2 + 1] = x1i + x3r; - a[j3] = x1r - x3i; - a[j3 + 1] = x1i - x3r; - wn4r = w[1]; - csc1 = w[2]; - csc3 = w[3]; - wd1r = 1; - wd1i = 0; - wd3r = 1; - wd3i = 0; - k = 0; - for (j = 2; j < mh - 2; j += 4) { - k += 4; - wk1r = csc1 * (wd1r + w[k]); - wk1i = csc1 * (wd1i + w[k + 1]); - wk3r = csc3 * (wd3r + w[k + 2]); - wk3i = csc3 * (wd3i + w[k + 3]); - wd1r = w[k]; - wd1i = w[k + 1]; - wd3r = w[k + 2]; - wd3i = w[k + 3]; - j1 = j + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j] + a[j2]; - x0i = -a[j + 1] - a[j2 + 1]; - x1r = a[j] - a[j2]; - x1i = -a[j + 1] + a[j2 + 1]; - y0r = a[j + 2] + a[j2 + 2]; - y0i = -a[j + 3] - a[j2 + 3]; - y1r = a[j + 2] - a[j2 + 2]; - y1i = -a[j + 3] + a[j2 + 3]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - y2r = a[j1 + 2] + a[j3 + 2]; - y2i = a[j1 + 3] + a[j3 + 3]; - y3r = a[j1 + 2] - a[j3 + 2]; - y3i = a[j1 + 3] - a[j3 + 3]; - a[j] = x0r + x2r; - a[j + 1] = x0i - x2i; - a[j + 2] = y0r + y2r; - a[j + 3] = y0i - y2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i + x2i; - a[j1 + 2] = y0r - y2r; - a[j1 + 3] = y0i + y2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2] = wk1r * x0r - wk1i * x0i; - a[j2 + 1] = wk1r * x0i + wk1i * x0r; - x0r = y1r + y3i; - x0i = y1i + y3r; - a[j2 + 2] = wd1r * x0r - wd1i * x0i; - a[j2 + 3] = wd1r * x0i + wd1i * x0r; - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3] = wk3r * x0r + wk3i * x0i; - a[j3 + 1] = wk3r * x0i - wk3i * x0r; - x0r = y1r - y3i; - x0i = y1i - y3r; - a[j3 + 2] = wd3r * x0r + wd3i * x0i; - a[j3 + 3] = wd3r * x0i - wd3i * x0r; - j0 = m - j; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0] + a[j2]; - x0i = -a[j0 + 1] - a[j2 + 1]; - x1r = a[j0] - a[j2]; - x1i = -a[j0 + 1] + a[j2 + 1]; - y0r = a[j0 - 2] + a[j2 - 2]; - y0i = -a[j0 - 1] - a[j2 - 1]; - y1r = a[j0 - 2] - a[j2 - 2]; - y1i = -a[j0 - 1] + a[j2 - 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - y2r = a[j1 - 2] + a[j3 - 2]; - y2i = a[j1 - 1] + a[j3 - 1]; - y3r = a[j1 - 2] - a[j3 - 2]; - y3i = a[j1 - 1] - a[j3 - 1]; - a[j0] = x0r + x2r; - a[j0 + 1] = x0i - x2i; - a[j0 - 2] = y0r + y2r; - a[j0 - 1] = y0i - y2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i + x2i; - a[j1 - 2] = y0r - y2r; - a[j1 - 1] = y0i + y2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2] = wk1i * x0r - wk1r * x0i; - a[j2 + 1] = wk1i * x0i + wk1r * x0r; - x0r = y1r + y3i; - x0i = y1i + y3r; - a[j2 - 2] = wd1i * x0r - wd1r * x0i; - a[j2 - 1] = wd1i * x0i + wd1r * x0r; - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3] = wk3i * x0r + wk3r * x0i; - a[j3 + 1] = wk3i * x0i - wk3r * x0r; - x0r = y1r - y3i; - x0i = y1i - y3r; - a[j3 - 2] = wd3i * x0r + wd3r * x0i; - a[j3 - 1] = wd3i * x0i - wd3r * x0r; - } - wk1r = csc1 * (wd1r + wn4r); - wk1i = csc1 * (wd1i + wn4r); - wk3r = csc3 * (wd3r - wn4r); - wk3i = csc3 * (wd3i - wn4r); - j0 = mh; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0 - 2] + a[j2 - 2]; - x0i = -a[j0 - 1] - a[j2 - 1]; - x1r = a[j0 - 2] - a[j2 - 2]; - x1i = -a[j0 - 1] + a[j2 - 1]; - x2r = a[j1 - 2] + a[j3 - 2]; - x2i = a[j1 - 1] + a[j3 - 1]; - x3r = a[j1 - 2] - a[j3 - 2]; - x3i = a[j1 - 1] - a[j3 - 1]; - a[j0 - 2] = x0r + x2r; - a[j0 - 1] = x0i - x2i; - a[j1 - 2] = x0r - x2r; - a[j1 - 1] = x0i + x2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2 - 2] = wk1r * x0r - wk1i * x0i; - a[j2 - 1] = wk1r * x0i + wk1i * x0r; - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3 - 2] = wk3r * x0r + wk3i * x0i; - a[j3 - 1] = wk3r * x0i - wk3i * x0r; - x0r = a[j0] + a[j2]; - x0i = -a[j0 + 1] - a[j2 + 1]; - x1r = a[j0] - a[j2]; - x1i = -a[j0 + 1] + a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j0] = x0r + x2r; - a[j0 + 1] = x0i - x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i + x2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2] = wn4r * (x0r - x0i); - a[j2 + 1] = wn4r * (x0i + x0r); - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3] = -wn4r * (x0r + x0i); - a[j3 + 1] = -wn4r * (x0i - x0r); - x0r = a[j0 + 2] + a[j2 + 2]; - x0i = -a[j0 + 3] - a[j2 + 3]; - x1r = a[j0 + 2] - a[j2 + 2]; - x1i = -a[j0 + 3] + a[j2 + 3]; - x2r = a[j1 + 2] + a[j3 + 2]; - x2i = a[j1 + 3] + a[j3 + 3]; - x3r = a[j1 + 2] - a[j3 + 2]; - x3i = a[j1 + 3] - a[j3 + 3]; - a[j0 + 2] = x0r + x2r; - a[j0 + 3] = x0i - x2i; - a[j1 + 2] = x0r - x2r; - a[j1 + 3] = x0i + x2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2 + 2] = wk1i * x0r - wk1r * x0i; - a[j2 + 3] = wk1i * x0i + wk1r * x0r; - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3 + 2] = wk3i * x0r + wk3r * x0i; - a[j3 + 3] = wk3i * x0i - wk3r * x0r; -} - - -#ifdef USE_CDFT_THREADS -struct cdft_arg_st { - int n0; - int n; - double *a; - int nw; - double *w; -}; -typedef struct cdft_arg_st cdft_arg_t; - - -void cftrec4_th(int n, double *a, int nw, double *w) -{ - void *cftrec1_th(void *p); - void *cftrec2_th(void *p); - int i, idiv4, m, nthread; - cdft_thread_t th[4]; - cdft_arg_t ag[4]; - - nthread = 2; - idiv4 = 0; - m = n >> 1; - if (n > CDFT_4THREADS_BEGIN_N) { - nthread = 4; - idiv4 = 1; - m >>= 1; - } - for (i = 0; i < nthread; i++) { - ag[i].n0 = n; - ag[i].n = m; - ag[i].a = &a[i * m]; - ag[i].nw = nw; - ag[i].w = w; - if (i != idiv4) { - cdft_thread_create(&th[i], cftrec1_th, &ag[i]); - } else { - cdft_thread_create(&th[i], cftrec2_th, &ag[i]); - } - } - for (i = 0; i < nthread; i++) { - cdft_thread_wait(th[i]); - } -} - - -void *cftrec1_th(void *p) -{ - int cfttree(int n, int j, int k, double *a, int nw, double *w); - void cftleaf(int n, int isplt, double *a, int nw, double *w); - void cftmdl1(int n, double *a, double *w); - int isplt, j, k, m, n, n0, nw; - double *a, *w; - - n0 = ((cdft_arg_t *) p)->n0; - n = ((cdft_arg_t *) p)->n; - a = ((cdft_arg_t *) p)->a; - nw = ((cdft_arg_t *) p)->nw; - w = ((cdft_arg_t *) p)->w; - m = n0; - while (m > 512) { - m >>= 2; - cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]); - } - cftleaf(m, 1, &a[n - m], nw, w); - k = 0; - for (j = n - m; j > 0; j -= m) { - k++; - isplt = cfttree(m, j, k, a, nw, w); - cftleaf(m, isplt, &a[j - m], nw, w); - } - return (void *) 0; -} - - -void *cftrec2_th(void *p) -{ - int cfttree(int n, int j, int k, double *a, int nw, double *w); - void cftleaf(int n, int isplt, double *a, int nw, double *w); - void cftmdl2(int n, double *a, double *w); - int isplt, j, k, m, n, n0, nw; - double *a, *w; - - n0 = ((cdft_arg_t *) p)->n0; - n = ((cdft_arg_t *) p)->n; - a = ((cdft_arg_t *) p)->a; - nw = ((cdft_arg_t *) p)->nw; - w = ((cdft_arg_t *) p)->w; - k = 1; - m = n0; - while (m > 512) { - m >>= 2; - k <<= 2; - cftmdl2(m, &a[n - m], &w[nw - m]); - } - cftleaf(m, 0, &a[n - m], nw, w); - k >>= 1; - for (j = n - m; j > 0; j -= m) { - k++; - isplt = cfttree(m, j, k, a, nw, w); - cftleaf(m, isplt, &a[j - m], nw, w); - } - return (void *) 0; -} -#endif /* USE_CDFT_THREADS */ - - -void cftrec4(int n, double *a, int nw, double *w) -{ - int cfttree(int n, int j, int k, double *a, int nw, double *w); - void cftleaf(int n, int isplt, double *a, int nw, double *w); - void cftmdl1(int n, double *a, double *w); - int isplt, j, k, m; - - m = n; - while (m > 512) { - m >>= 2; - cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]); - } - cftleaf(m, 1, &a[n - m], nw, w); - k = 0; - for (j = n - m; j > 0; j -= m) { - k++; - isplt = cfttree(m, j, k, a, nw, w); - cftleaf(m, isplt, &a[j - m], nw, w); - } -} - - -int cfttree(int n, int j, int k, double *a, int nw, double *w) -{ - void cftmdl1(int n, double *a, double *w); - void cftmdl2(int n, double *a, double *w); - int i, isplt, m; - - if ((k & 3) != 0) { - isplt = k & 1; - if (isplt != 0) { - cftmdl1(n, &a[j - n], &w[nw - (n >> 1)]); - } else { - cftmdl2(n, &a[j - n], &w[nw - n]); - } - } else { - m = n; - for (i = k; (i & 3) == 0; i >>= 2) { - m <<= 2; - } - isplt = i & 1; - if (isplt != 0) { - while (m > 128) { - cftmdl1(m, &a[j - m], &w[nw - (m >> 1)]); - m >>= 2; - } - } else { - while (m > 128) { - cftmdl2(m, &a[j - m], &w[nw - m]); - m >>= 2; - } - } - } - return isplt; -} - - -void cftleaf(int n, int isplt, double *a, int nw, double *w) -{ - void cftmdl1(int n, double *a, double *w); - void cftmdl2(int n, double *a, double *w); - void cftf161(double *a, double *w); - void cftf162(double *a, double *w); - void cftf081(double *a, double *w); - void cftf082(double *a, double *w); - - if (n == 512) { - cftmdl1(128, a, &w[nw - 64]); - cftf161(a, &w[nw - 8]); - cftf162(&a[32], &w[nw - 32]); - cftf161(&a[64], &w[nw - 8]); - cftf161(&a[96], &w[nw - 8]); - cftmdl2(128, &a[128], &w[nw - 128]); - cftf161(&a[128], &w[nw - 8]); - cftf162(&a[160], &w[nw - 32]); - cftf161(&a[192], &w[nw - 8]); - cftf162(&a[224], &w[nw - 32]); - cftmdl1(128, &a[256], &w[nw - 64]); - cftf161(&a[256], &w[nw - 8]); - cftf162(&a[288], &w[nw - 32]); - cftf161(&a[320], &w[nw - 8]); - cftf161(&a[352], &w[nw - 8]); - if (isplt != 0) { - cftmdl1(128, &a[384], &w[nw - 64]); - cftf161(&a[480], &w[nw - 8]); - } else { - cftmdl2(128, &a[384], &w[nw - 128]); - cftf162(&a[480], &w[nw - 32]); - } - cftf161(&a[384], &w[nw - 8]); - cftf162(&a[416], &w[nw - 32]); - cftf161(&a[448], &w[nw - 8]); - } else { - cftmdl1(64, a, &w[nw - 32]); - cftf081(a, &w[nw - 8]); - cftf082(&a[16], &w[nw - 8]); - cftf081(&a[32], &w[nw - 8]); - cftf081(&a[48], &w[nw - 8]); - cftmdl2(64, &a[64], &w[nw - 64]); - cftf081(&a[64], &w[nw - 8]); - cftf082(&a[80], &w[nw - 8]); - cftf081(&a[96], &w[nw - 8]); - cftf082(&a[112], &w[nw - 8]); - cftmdl1(64, &a[128], &w[nw - 32]); - cftf081(&a[128], &w[nw - 8]); - cftf082(&a[144], &w[nw - 8]); - cftf081(&a[160], &w[nw - 8]); - cftf081(&a[176], &w[nw - 8]); - if (isplt != 0) { - cftmdl1(64, &a[192], &w[nw - 32]); - cftf081(&a[240], &w[nw - 8]); - } else { - cftmdl2(64, &a[192], &w[nw - 64]); - cftf082(&a[240], &w[nw - 8]); - } - cftf081(&a[192], &w[nw - 8]); - cftf082(&a[208], &w[nw - 8]); - cftf081(&a[224], &w[nw - 8]); - } -} - - -void cftmdl1(int n, double *a, double *w) -{ - int j, j0, j1, j2, j3, k, m, mh; - double wn4r, wk1r, wk1i, wk3r, wk3i; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - mh = n >> 3; - m = 2 * mh; - j1 = m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[0] + a[j2]; - x0i = a[1] + a[j2 + 1]; - x1r = a[0] - a[j2]; - x1i = a[1] - a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - a[j2] = x1r - x3i; - a[j2 + 1] = x1i + x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i - x3r; - wn4r = w[1]; - k = 0; - for (j = 2; j < mh; j += 2) { - k += 4; - wk1r = w[k]; - wk1i = w[k + 1]; - wk3r = w[k + 2]; - wk3i = w[k + 3]; - j1 = j + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j] + a[j2]; - x0i = a[j + 1] + a[j2 + 1]; - x1r = a[j] - a[j2]; - x1i = a[j + 1] - a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2] = wk1r * x0r - wk1i * x0i; - a[j2 + 1] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = wk3r * x0r + wk3i * x0i; - a[j3 + 1] = wk3r * x0i - wk3i * x0r; - j0 = m - j; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0] + a[j2]; - x0i = a[j0 + 1] + a[j2 + 1]; - x1r = a[j0] - a[j2]; - x1i = a[j0 + 1] - a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j0] = x0r + x2r; - a[j0 + 1] = x0i + x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2] = wk1i * x0r - wk1r * x0i; - a[j2 + 1] = wk1i * x0i + wk1r * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = wk3i * x0r + wk3r * x0i; - a[j3 + 1] = wk3i * x0i - wk3r * x0r; - } - j0 = mh; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0] + a[j2]; - x0i = a[j0 + 1] + a[j2 + 1]; - x1r = a[j0] - a[j2]; - x1i = a[j0 + 1] - a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j0] = x0r + x2r; - a[j0 + 1] = x0i + x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2] = wn4r * (x0r - x0i); - a[j2 + 1] = wn4r * (x0i + x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = -wn4r * (x0r + x0i); - a[j3 + 1] = -wn4r * (x0i - x0r); -} - - -void cftmdl2(int n, double *a, double *w) -{ - int j, j0, j1, j2, j3, k, kr, m, mh; - double wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i; - - mh = n >> 3; - m = 2 * mh; - wn4r = w[1]; - j1 = m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[0] - a[j2 + 1]; - x0i = a[1] + a[j2]; - x1r = a[0] + a[j2 + 1]; - x1i = a[1] - a[j2]; - x2r = a[j1] - a[j3 + 1]; - x2i = a[j1 + 1] + a[j3]; - x3r = a[j1] + a[j3 + 1]; - x3i = a[j1 + 1] - a[j3]; - y0r = wn4r * (x2r - x2i); - y0i = wn4r * (x2i + x2r); - a[0] = x0r + y0r; - a[1] = x0i + y0i; - a[j1] = x0r - y0r; - a[j1 + 1] = x0i - y0i; - y0r = wn4r * (x3r - x3i); - y0i = wn4r * (x3i + x3r); - a[j2] = x1r - y0i; - a[j2 + 1] = x1i + y0r; - a[j3] = x1r + y0i; - a[j3 + 1] = x1i - y0r; - k = 0; - kr = 2 * m; - for (j = 2; j < mh; j += 2) { - k += 4; - wk1r = w[k]; - wk1i = w[k + 1]; - wk3r = w[k + 2]; - wk3i = w[k + 3]; - kr -= 4; - wd1i = w[kr]; - wd1r = w[kr + 1]; - wd3i = w[kr + 2]; - wd3r = w[kr + 3]; - j1 = j + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j] - a[j2 + 1]; - x0i = a[j + 1] + a[j2]; - x1r = a[j] + a[j2 + 1]; - x1i = a[j + 1] - a[j2]; - x2r = a[j1] - a[j3 + 1]; - x2i = a[j1 + 1] + a[j3]; - x3r = a[j1] + a[j3 + 1]; - x3i = a[j1 + 1] - a[j3]; - y0r = wk1r * x0r - wk1i * x0i; - y0i = wk1r * x0i + wk1i * x0r; - y2r = wd1r * x2r - wd1i * x2i; - y2i = wd1r * x2i + wd1i * x2r; - a[j] = y0r + y2r; - a[j + 1] = y0i + y2i; - a[j1] = y0r - y2r; - a[j1 + 1] = y0i - y2i; - y0r = wk3r * x1r + wk3i * x1i; - y0i = wk3r * x1i - wk3i * x1r; - y2r = wd3r * x3r + wd3i * x3i; - y2i = wd3r * x3i - wd3i * x3r; - a[j2] = y0r + y2r; - a[j2 + 1] = y0i + y2i; - a[j3] = y0r - y2r; - a[j3 + 1] = y0i - y2i; - j0 = m - j; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0] - a[j2 + 1]; - x0i = a[j0 + 1] + a[j2]; - x1r = a[j0] + a[j2 + 1]; - x1i = a[j0 + 1] - a[j2]; - x2r = a[j1] - a[j3 + 1]; - x2i = a[j1 + 1] + a[j3]; - x3r = a[j1] + a[j3 + 1]; - x3i = a[j1 + 1] - a[j3]; - y0r = wd1i * x0r - wd1r * x0i; - y0i = wd1i * x0i + wd1r * x0r; - y2r = wk1i * x2r - wk1r * x2i; - y2i = wk1i * x2i + wk1r * x2r; - a[j0] = y0r + y2r; - a[j0 + 1] = y0i + y2i; - a[j1] = y0r - y2r; - a[j1 + 1] = y0i - y2i; - y0r = wd3i * x1r + wd3r * x1i; - y0i = wd3i * x1i - wd3r * x1r; - y2r = wk3i * x3r + wk3r * x3i; - y2i = wk3i * x3i - wk3r * x3r; - a[j2] = y0r + y2r; - a[j2 + 1] = y0i + y2i; - a[j3] = y0r - y2r; - a[j3 + 1] = y0i - y2i; - } - wk1r = w[m]; - wk1i = w[m + 1]; - j0 = mh; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0] - a[j2 + 1]; - x0i = a[j0 + 1] + a[j2]; - x1r = a[j0] + a[j2 + 1]; - x1i = a[j0 + 1] - a[j2]; - x2r = a[j1] - a[j3 + 1]; - x2i = a[j1 + 1] + a[j3]; - x3r = a[j1] + a[j3 + 1]; - x3i = a[j1 + 1] - a[j3]; - y0r = wk1r * x0r - wk1i * x0i; - y0i = wk1r * x0i + wk1i * x0r; - y2r = wk1i * x2r - wk1r * x2i; - y2i = wk1i * x2i + wk1r * x2r; - a[j0] = y0r + y2r; - a[j0 + 1] = y0i + y2i; - a[j1] = y0r - y2r; - a[j1 + 1] = y0i - y2i; - y0r = wk1i * x1r - wk1r * x1i; - y0i = wk1i * x1i + wk1r * x1r; - y2r = wk1r * x3r - wk1i * x3i; - y2i = wk1r * x3i + wk1i * x3r; - a[j2] = y0r - y2r; - a[j2 + 1] = y0i - y2i; - a[j3] = y0r + y2r; - a[j3 + 1] = y0i + y2i; -} - - -void cftfx41(int n, double *a, int nw, double *w) -{ - void cftf161(double *a, double *w); - void cftf162(double *a, double *w); - void cftf081(double *a, double *w); - void cftf082(double *a, double *w); - - if (n == 128) { - cftf161(a, &w[nw - 8]); - cftf162(&a[32], &w[nw - 32]); - cftf161(&a[64], &w[nw - 8]); - cftf161(&a[96], &w[nw - 8]); - } else { - cftf081(a, &w[nw - 8]); - cftf082(&a[16], &w[nw - 8]); - cftf081(&a[32], &w[nw - 8]); - cftf081(&a[48], &w[nw - 8]); - } -} - - -void cftf161(double *a, double *w) -{ - double wn4r, wk1r, wk1i, - x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, - y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, - y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, - y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, - y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; - - wn4r = w[1]; - wk1r = w[2]; - wk1i = w[3]; - x0r = a[0] + a[16]; - x0i = a[1] + a[17]; - x1r = a[0] - a[16]; - x1i = a[1] - a[17]; - x2r = a[8] + a[24]; - x2i = a[9] + a[25]; - x3r = a[8] - a[24]; - x3i = a[9] - a[25]; - y0r = x0r + x2r; - y0i = x0i + x2i; - y4r = x0r - x2r; - y4i = x0i - x2i; - y8r = x1r - x3i; - y8i = x1i + x3r; - y12r = x1r + x3i; - y12i = x1i - x3r; - x0r = a[2] + a[18]; - x0i = a[3] + a[19]; - x1r = a[2] - a[18]; - x1i = a[3] - a[19]; - x2r = a[10] + a[26]; - x2i = a[11] + a[27]; - x3r = a[10] - a[26]; - x3i = a[11] - a[27]; - y1r = x0r + x2r; - y1i = x0i + x2i; - y5r = x0r - x2r; - y5i = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - y9r = wk1r * x0r - wk1i * x0i; - y9i = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - y13r = wk1i * x0r - wk1r * x0i; - y13i = wk1i * x0i + wk1r * x0r; - x0r = a[4] + a[20]; - x0i = a[5] + a[21]; - x1r = a[4] - a[20]; - x1i = a[5] - a[21]; - x2r = a[12] + a[28]; - x2i = a[13] + a[29]; - x3r = a[12] - a[28]; - x3i = a[13] - a[29]; - y2r = x0r + x2r; - y2i = x0i + x2i; - y6r = x0r - x2r; - y6i = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - y10r = wn4r * (x0r - x0i); - y10i = wn4r * (x0i + x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - y14r = wn4r * (x0r + x0i); - y14i = wn4r * (x0i - x0r); - x0r = a[6] + a[22]; - x0i = a[7] + a[23]; - x1r = a[6] - a[22]; - x1i = a[7] - a[23]; - x2r = a[14] + a[30]; - x2i = a[15] + a[31]; - x3r = a[14] - a[30]; - x3i = a[15] - a[31]; - y3r = x0r + x2r; - y3i = x0i + x2i; - y7r = x0r - x2r; - y7i = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - y11r = wk1i * x0r - wk1r * x0i; - y11i = wk1i * x0i + wk1r * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - y15r = wk1r * x0r - wk1i * x0i; - y15i = wk1r * x0i + wk1i * x0r; - x0r = y12r - y14r; - x0i = y12i - y14i; - x1r = y12r + y14r; - x1i = y12i + y14i; - x2r = y13r - y15r; - x2i = y13i - y15i; - x3r = y13r + y15r; - x3i = y13i + y15i; - a[24] = x0r + x2r; - a[25] = x0i + x2i; - a[26] = x0r - x2r; - a[27] = x0i - x2i; - a[28] = x1r - x3i; - a[29] = x1i + x3r; - a[30] = x1r + x3i; - a[31] = x1i - x3r; - x0r = y8r + y10r; - x0i = y8i + y10i; - x1r = y8r - y10r; - x1i = y8i - y10i; - x2r = y9r + y11r; - x2i = y9i + y11i; - x3r = y9r - y11r; - x3i = y9i - y11i; - a[16] = x0r + x2r; - a[17] = x0i + x2i; - a[18] = x0r - x2r; - a[19] = x0i - x2i; - a[20] = x1r - x3i; - a[21] = x1i + x3r; - a[22] = x1r + x3i; - a[23] = x1i - x3r; - x0r = y5r - y7i; - x0i = y5i + y7r; - x2r = wn4r * (x0r - x0i); - x2i = wn4r * (x0i + x0r); - x0r = y5r + y7i; - x0i = y5i - y7r; - x3r = wn4r * (x0r - x0i); - x3i = wn4r * (x0i + x0r); - x0r = y4r - y6i; - x0i = y4i + y6r; - x1r = y4r + y6i; - x1i = y4i - y6r; - a[8] = x0r + x2r; - a[9] = x0i + x2i; - a[10] = x0r - x2r; - a[11] = x0i - x2i; - a[12] = x1r - x3i; - a[13] = x1i + x3r; - a[14] = x1r + x3i; - a[15] = x1i - x3r; - x0r = y0r + y2r; - x0i = y0i + y2i; - x1r = y0r - y2r; - x1i = y0i - y2i; - x2r = y1r + y3r; - x2i = y1i + y3i; - x3r = y1r - y3r; - x3i = y1i - y3i; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[2] = x0r - x2r; - a[3] = x0i - x2i; - a[4] = x1r - x3i; - a[5] = x1i + x3r; - a[6] = x1r + x3i; - a[7] = x1i - x3r; -} - - -void cftf162(double *a, double *w) -{ - double wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, - x0r, x0i, x1r, x1i, x2r, x2i, - y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, - y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, - y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, - y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; - - wn4r = w[1]; - wk1r = w[4]; - wk1i = w[5]; - wk3r = w[6]; - wk3i = -w[7]; - wk2r = w[8]; - wk2i = w[9]; - x1r = a[0] - a[17]; - x1i = a[1] + a[16]; - x0r = a[8] - a[25]; - x0i = a[9] + a[24]; - x2r = wn4r * (x0r - x0i); - x2i = wn4r * (x0i + x0r); - y0r = x1r + x2r; - y0i = x1i + x2i; - y4r = x1r - x2r; - y4i = x1i - x2i; - x1r = a[0] + a[17]; - x1i = a[1] - a[16]; - x0r = a[8] + a[25]; - x0i = a[9] - a[24]; - x2r = wn4r * (x0r - x0i); - x2i = wn4r * (x0i + x0r); - y8r = x1r - x2i; - y8i = x1i + x2r; - y12r = x1r + x2i; - y12i = x1i - x2r; - x0r = a[2] - a[19]; - x0i = a[3] + a[18]; - x1r = wk1r * x0r - wk1i * x0i; - x1i = wk1r * x0i + wk1i * x0r; - x0r = a[10] - a[27]; - x0i = a[11] + a[26]; - x2r = wk3i * x0r - wk3r * x0i; - x2i = wk3i * x0i + wk3r * x0r; - y1r = x1r + x2r; - y1i = x1i + x2i; - y5r = x1r - x2r; - y5i = x1i - x2i; - x0r = a[2] + a[19]; - x0i = a[3] - a[18]; - x1r = wk3r * x0r - wk3i * x0i; - x1i = wk3r * x0i + wk3i * x0r; - x0r = a[10] + a[27]; - x0i = a[11] - a[26]; - x2r = wk1r * x0r + wk1i * x0i; - x2i = wk1r * x0i - wk1i * x0r; - y9r = x1r - x2r; - y9i = x1i - x2i; - y13r = x1r + x2r; - y13i = x1i + x2i; - x0r = a[4] - a[21]; - x0i = a[5] + a[20]; - x1r = wk2r * x0r - wk2i * x0i; - x1i = wk2r * x0i + wk2i * x0r; - x0r = a[12] - a[29]; - x0i = a[13] + a[28]; - x2r = wk2i * x0r - wk2r * x0i; - x2i = wk2i * x0i + wk2r * x0r; - y2r = x1r + x2r; - y2i = x1i + x2i; - y6r = x1r - x2r; - y6i = x1i - x2i; - x0r = a[4] + a[21]; - x0i = a[5] - a[20]; - x1r = wk2i * x0r - wk2r * x0i; - x1i = wk2i * x0i + wk2r * x0r; - x0r = a[12] + a[29]; - x0i = a[13] - a[28]; - x2r = wk2r * x0r - wk2i * x0i; - x2i = wk2r * x0i + wk2i * x0r; - y10r = x1r - x2r; - y10i = x1i - x2i; - y14r = x1r + x2r; - y14i = x1i + x2i; - x0r = a[6] - a[23]; - x0i = a[7] + a[22]; - x1r = wk3r * x0r - wk3i * x0i; - x1i = wk3r * x0i + wk3i * x0r; - x0r = a[14] - a[31]; - x0i = a[15] + a[30]; - x2r = wk1i * x0r - wk1r * x0i; - x2i = wk1i * x0i + wk1r * x0r; - y3r = x1r + x2r; - y3i = x1i + x2i; - y7r = x1r - x2r; - y7i = x1i - x2i; - x0r = a[6] + a[23]; - x0i = a[7] - a[22]; - x1r = wk1i * x0r + wk1r * x0i; - x1i = wk1i * x0i - wk1r * x0r; - x0r = a[14] + a[31]; - x0i = a[15] - a[30]; - x2r = wk3i * x0r - wk3r * x0i; - x2i = wk3i * x0i + wk3r * x0r; - y11r = x1r + x2r; - y11i = x1i + x2i; - y15r = x1r - x2r; - y15i = x1i - x2i; - x1r = y0r + y2r; - x1i = y0i + y2i; - x2r = y1r + y3r; - x2i = y1i + y3i; - a[0] = x1r + x2r; - a[1] = x1i + x2i; - a[2] = x1r - x2r; - a[3] = x1i - x2i; - x1r = y0r - y2r; - x1i = y0i - y2i; - x2r = y1r - y3r; - x2i = y1i - y3i; - a[4] = x1r - x2i; - a[5] = x1i + x2r; - a[6] = x1r + x2i; - a[7] = x1i - x2r; - x1r = y4r - y6i; - x1i = y4i + y6r; - x0r = y5r - y7i; - x0i = y5i + y7r; - x2r = wn4r * (x0r - x0i); - x2i = wn4r * (x0i + x0r); - a[8] = x1r + x2r; - a[9] = x1i + x2i; - a[10] = x1r - x2r; - a[11] = x1i - x2i; - x1r = y4r + y6i; - x1i = y4i - y6r; - x0r = y5r + y7i; - x0i = y5i - y7r; - x2r = wn4r * (x0r - x0i); - x2i = wn4r * (x0i + x0r); - a[12] = x1r - x2i; - a[13] = x1i + x2r; - a[14] = x1r + x2i; - a[15] = x1i - x2r; - x1r = y8r + y10r; - x1i = y8i + y10i; - x2r = y9r - y11r; - x2i = y9i - y11i; - a[16] = x1r + x2r; - a[17] = x1i + x2i; - a[18] = x1r - x2r; - a[19] = x1i - x2i; - x1r = y8r - y10r; - x1i = y8i - y10i; - x2r = y9r + y11r; - x2i = y9i + y11i; - a[20] = x1r - x2i; - a[21] = x1i + x2r; - a[22] = x1r + x2i; - a[23] = x1i - x2r; - x1r = y12r - y14i; - x1i = y12i + y14r; - x0r = y13r + y15i; - x0i = y13i - y15r; - x2r = wn4r * (x0r - x0i); - x2i = wn4r * (x0i + x0r); - a[24] = x1r + x2r; - a[25] = x1i + x2i; - a[26] = x1r - x2r; - a[27] = x1i - x2i; - x1r = y12r + y14i; - x1i = y12i - y14r; - x0r = y13r - y15i; - x0i = y13i + y15r; - x2r = wn4r * (x0r - x0i); - x2i = wn4r * (x0i + x0r); - a[28] = x1r - x2i; - a[29] = x1i + x2r; - a[30] = x1r + x2i; - a[31] = x1i - x2r; -} - - -void cftf081(double *a, double *w) -{ - double wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, - y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, - y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; - - wn4r = w[1]; - x0r = a[0] + a[8]; - x0i = a[1] + a[9]; - x1r = a[0] - a[8]; - x1i = a[1] - a[9]; - x2r = a[4] + a[12]; - x2i = a[5] + a[13]; - x3r = a[4] - a[12]; - x3i = a[5] - a[13]; - y0r = x0r + x2r; - y0i = x0i + x2i; - y2r = x0r - x2r; - y2i = x0i - x2i; - y1r = x1r - x3i; - y1i = x1i + x3r; - y3r = x1r + x3i; - y3i = x1i - x3r; - x0r = a[2] + a[10]; - x0i = a[3] + a[11]; - x1r = a[2] - a[10]; - x1i = a[3] - a[11]; - x2r = a[6] + a[14]; - x2i = a[7] + a[15]; - x3r = a[6] - a[14]; - x3i = a[7] - a[15]; - y4r = x0r + x2r; - y4i = x0i + x2i; - y6r = x0r - x2r; - y6i = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - x2r = x1r + x3i; - x2i = x1i - x3r; - y5r = wn4r * (x0r - x0i); - y5i = wn4r * (x0r + x0i); - y7r = wn4r * (x2r - x2i); - y7i = wn4r * (x2r + x2i); - a[8] = y1r + y5r; - a[9] = y1i + y5i; - a[10] = y1r - y5r; - a[11] = y1i - y5i; - a[12] = y3r - y7i; - a[13] = y3i + y7r; - a[14] = y3r + y7i; - a[15] = y3i - y7r; - a[0] = y0r + y4r; - a[1] = y0i + y4i; - a[2] = y0r - y4r; - a[3] = y0i - y4i; - a[4] = y2r - y6i; - a[5] = y2i + y6r; - a[6] = y2r + y6i; - a[7] = y2i - y6r; -} - - -void cftf082(double *a, double *w) -{ - double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, - y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, - y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; - - wn4r = w[1]; - wk1r = w[2]; - wk1i = w[3]; - y0r = a[0] - a[9]; - y0i = a[1] + a[8]; - y1r = a[0] + a[9]; - y1i = a[1] - a[8]; - x0r = a[4] - a[13]; - x0i = a[5] + a[12]; - y2r = wn4r * (x0r - x0i); - y2i = wn4r * (x0i + x0r); - x0r = a[4] + a[13]; - x0i = a[5] - a[12]; - y3r = wn4r * (x0r - x0i); - y3i = wn4r * (x0i + x0r); - x0r = a[2] - a[11]; - x0i = a[3] + a[10]; - y4r = wk1r * x0r - wk1i * x0i; - y4i = wk1r * x0i + wk1i * x0r; - x0r = a[2] + a[11]; - x0i = a[3] - a[10]; - y5r = wk1i * x0r - wk1r * x0i; - y5i = wk1i * x0i + wk1r * x0r; - x0r = a[6] - a[15]; - x0i = a[7] + a[14]; - y6r = wk1i * x0r - wk1r * x0i; - y6i = wk1i * x0i + wk1r * x0r; - x0r = a[6] + a[15]; - x0i = a[7] - a[14]; - y7r = wk1r * x0r - wk1i * x0i; - y7i = wk1r * x0i + wk1i * x0r; - x0r = y0r + y2r; - x0i = y0i + y2i; - x1r = y4r + y6r; - x1i = y4i + y6i; - a[0] = x0r + x1r; - a[1] = x0i + x1i; - a[2] = x0r - x1r; - a[3] = x0i - x1i; - x0r = y0r - y2r; - x0i = y0i - y2i; - x1r = y4r - y6r; - x1i = y4i - y6i; - a[4] = x0r - x1i; - a[5] = x0i + x1r; - a[6] = x0r + x1i; - a[7] = x0i - x1r; - x0r = y1r - y3i; - x0i = y1i + y3r; - x1r = y5r - y7r; - x1i = y5i - y7i; - a[8] = x0r + x1r; - a[9] = x0i + x1i; - a[10] = x0r - x1r; - a[11] = x0i - x1i; - x0r = y1r + y3i; - x0i = y1i - y3r; - x1r = y5r + y7r; - x1i = y5i + y7i; - a[12] = x0r - x1i; - a[13] = x0i + x1r; - a[14] = x0r + x1i; - a[15] = x0i - x1r; -} - - -void cftf040(double *a) -{ - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - x0r = a[0] + a[4]; - x0i = a[1] + a[5]; - x1r = a[0] - a[4]; - x1i = a[1] - a[5]; - x2r = a[2] + a[6]; - x2i = a[3] + a[7]; - x3r = a[2] - a[6]; - x3i = a[3] - a[7]; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[2] = x1r - x3i; - a[3] = x1i + x3r; - a[4] = x0r - x2r; - a[5] = x0i - x2i; - a[6] = x1r + x3i; - a[7] = x1i - x3r; -} - - -void cftb040(double *a) -{ - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - x0r = a[0] + a[4]; - x0i = a[1] + a[5]; - x1r = a[0] - a[4]; - x1i = a[1] - a[5]; - x2r = a[2] + a[6]; - x2i = a[3] + a[7]; - x3r = a[2] - a[6]; - x3i = a[3] - a[7]; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[2] = x1r + x3i; - a[3] = x1i - x3r; - a[4] = x0r - x2r; - a[5] = x0i - x2i; - a[6] = x1r - x3i; - a[7] = x1i + x3r; -} - - -void cftx020(double *a) -{ - double x0r, x0i; - - x0r = a[0] - a[2]; - x0i = a[1] - a[3]; - a[0] += a[2]; - a[1] += a[3]; - a[2] = x0r; - a[3] = x0i; -} - - -void rftfsub(int n, double *a, int nc, double *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr, xi, yr, yi; - - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5 - c[nc - kk]; - wki = c[kk]; - xr = a[j] - a[k]; - xi = a[j + 1] + a[k + 1]; - yr = wkr * xr - wki * xi; - yi = wkr * xi + wki * xr; - a[j] -= yr; - a[j + 1] -= yi; - a[k] += yr; - a[k + 1] -= yi; - } -} - - -void rftbsub(int n, double *a, int nc, double *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr, xi, yr, yi; - - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5 - c[nc - kk]; - wki = c[kk]; - xr = a[j] - a[k]; - xi = a[j + 1] + a[k + 1]; - yr = wkr * xr + wki * xi; - yi = wkr * xi - wki * xr; - a[j] -= yr; - a[j + 1] -= yi; - a[k] += yr; - a[k + 1] -= yi; - } -} - - -void dctsub(int n, double *a, int nc, double *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr; - - m = n >> 1; - ks = nc / n; - kk = 0; - for (j = 1; j < m; j++) { - k = n - j; - kk += ks; - wkr = c[kk] - c[nc - kk]; - wki = c[kk] + c[nc - kk]; - xr = wki * a[j] - wkr * a[k]; - a[j] = wkr * a[j] + wki * a[k]; - a[k] = xr; - } - a[m] *= c[0]; -} - - -void dstsub(int n, double *a, int nc, double *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr; - - m = n >> 1; - ks = nc / n; - kk = 0; - for (j = 1; j < m; j++) { - k = n - j; - kk += ks; - wkr = c[kk] - c[nc - kk]; - wki = c[kk] + c[nc - kk]; - xr = wki * a[k] - wkr * a[j]; - a[k] = wkr * a[k] + wki * a[j]; - a[j] = xr; - } - a[m] *= c[0]; -} - -#if defined(__cplusplus) -} // end of extern "C" -#endif diff --git a/loris_library/Source/src/loris.h b/loris_library/Source/src/loris.h deleted file mode 100644 index 3e1d117..0000000 --- a/loris_library/Source/src/loris.h +++ /dev/null @@ -1,1020 +0,0 @@ -#ifndef INCLUDE_LORIS_H -#define INCLUDE_LORIS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * loris.h - * - * Header specifying C-linkable procedural interface for Loris. - * - * Main components of this interface: - * - version identification symbols - * - type declarations - * - Analyzer configuration - * - LinearEnvelope (formerly BreakpointEnvelope) operations - * - PartialList operations - * - Partial operations - * - Breakpoint operations - * - sound modeling functions for preparing PartialLists - * - utility functions for manipulating PartialLists - * - notification and exception handlers (all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function. The default one in Loris uses printf()). - * - * loris.h is generated automatically from loris.h.in. Do not modify loris.h - * - * Kelly Fitz, 4 Feb 2002 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -/* ---------------------------------------------------------------- */ -/* Version -/* -/* Define symbols that facilitate version/release identification. - */ - -#define LORIS_MAJOR_VERSION 1 -#define LORIS_MINOR_VERSION 8 -#define LORIS_SUBMINOR_VERSION -#define LORIS_VERSION_STR "Loris 1.8" - -/* ---------------------------------------------------------------- */ -/* Types -/* -/* The (class) types Breakpoint, LinearEnvelope, Partial, - and PartialList are imported from the Loris namespace. - The first three are classes, the latter is a typedef - for std::list< Loris::Partial >. - */ -#if defined(__cplusplus) - // include std library list header, declaring templates - // is too painful and fragile: - #include - - // declare Loris classes in Loris namespace: - namespace Loris - { - class Breakpoint; - class LinearEnvelope; - class Partial; - - // this typedef has to be copied from PartialList.h - typedef std::list< Loris::Partial > PartialList; - } - - // import those names into the global namespace - using Loris::Breakpoint; - using Loris::LinearEnvelope; - using Loris::Partial; - using Loris::PartialList; -#else - /* no classes, just declare types and use - opaque C pointers - */ - typedef struct Breakpoint Breakpoint; - typedef struct LinearEnvelope LinearEnvelope; - typedef struct PartialList PartialList; - typedef struct Partial Partial; -#endif - -/* - TODO - Maybe should also have loris_label_t and loris_size_t - defined, depending on configure. -*/ - -#if defined(__cplusplus) - extern "C" { -#endif - -/* ---------------------------------------------------------------- */ -/* Analyzer configuration -/* -/* An Analyzer represents a configuration of parameters for - performing Reassigned Bandwidth-Enhanced Additive Analysis - of sampled waveforms. This analysis process yields a collection - of Partials, each having a trio of synchronous, non-uniformly- - sampled breakpoint envelopes representing the time-varying - frequency, amplitude, and noisiness of a single bandwidth- - enhanced sinusoid. - - For more information about Reassigned Bandwidth-Enhanced - Analysis and the Reassigned Bandwidth-Enhanced Additive Sound - Model, refer to the Loris website: www.cerlsoundgroup.org/Loris/. - - In the procedural interface, there is only one Analyzer. - It must be configured by calling analyzer_configure before - any of the other analyzer operations can be performed. - */ - -void analyze( const double * buffer, unsigned int bufferSize, - double srate, PartialList * partials ); -/* Analyze an array of bufferSize (mono) samples at the given sample rate - (in Hz) and append the extracted Partials to the given - PartialList. - */ - -void analyzer_configure( double resolution, double windowWidth, void* tc); -/* Configure the sole Analyzer instance with the specified - frequency resolution (minimum instantaneous frequency - difference between Partials). All other Analyzer parameters - are computed from the specified frequency resolution. - - Construct the Analyzer instance if necessary. - - In the procedural interface, there is only one Analyzer. - It must be configured by calling analyzer_configure before - any of the other analyzer operations can be performed. - */ - -double analyzer_getAmpFloor( void ); -/* Return the amplitude floor (lowest detected spectral amplitude), - in (negative) dB, for the Loris Analyzer. - */ - -double analyzer_getCropTime( void ); -/* Return the crop time (maximum temporal displacement of a time- - frequency data point from the time-domain center of the analysis - window, beyond which data points are considered "unreliable") - for the Loris Analyzer. - */ - -double analyzer_getFreqDrift( void ); -/* Return the maximum allowable frequency difference between - consecutive Breakpoints in a Partial envelope for the Loris Analyzer. - */ - -double analyzer_getFreqFloor( void ); -/* Return the frequency floor (minimum instantaneous Partial - frequency), in Hz, for the Loris Analyzer. - */ - -double analyzer_getFreqResolution( void ); -/* Return the frequency resolution (minimum instantaneous frequency - difference between Partials) for the Loris Analyzer. - */ - -double analyzer_getHopTime( void ); -/* Return the hop time (which corresponds approximately to the - average density of Partial envelope Breakpoint data) for this - Analyzer. - */ - -double analyzer_getSidelobeLevel( void ); -/* Return the sidelobe attenutation level for the Kaiser analysis window in - positive dB. Higher numbers (e.g. 90) give very good sidelobe - rejection but cause the window to be longer in time. Smaller - numbers raise the level of the sidelobes, increasing the likelihood - of frequency-domain interference, but allow the window to be shorter - in time. - */ - -double analyzer_getWindowWidth( void ); -/* Return the frequency-domain main lobe width (measured between - zero-crossings) of the analysis window used by the Loris Analyzer. - */ - -void analyzer_setAmpFloor( double x ); -/* Set the amplitude floor (lowest detected spectral amplitude), in - (negative) dB, for the Loris Analyzer. - */ - -void analyzer_setBwRegionWidth( double x ); -/* Deprecated, use analyzer_storeResidueBandwidth instead. - */ - -void analyzer_setCropTime( double x ); -/* Set the crop time (maximum temporal displacement of a time- - frequency data point from the time-domain center of the analysis - window, beyond which data points are considered "unreliable") - for the Loris Analyzer. - */ - -void analyzer_setFreqDrift( double x ); -/* Set the maximum allowable frequency difference between - consecutive Breakpoints in a Partial envelope for the Loris Analyzer. - */ - -void analyzer_setFreqFloor( double x ); -/* Set the amplitude floor (minimum instantaneous Partial - frequency), in Hz, for the Loris Analyzer. - */ - -void analyzer_setFreqResolution( double x ); -/* Set the frequency resolution (minimum instantaneous frequency - difference between Partials) for the Loris Analyzer. (Does not cause - other parameters to be recomputed.) - */ - -void analyzer_setHopTime( double x ); -/* Set the hop time (which corresponds approximately to the average - density of Partial envelope Breakpoint data) for the Loris Analyzer. - */ - -void analyzer_setSidelobeLevel( double x ); -/* Set the sidelobe attenutation level for the Kaiser analysis window in - positive dB. Larger numbers (e.g. 90) give very good sidelobe - rejection but cause the window to be longer in time. Smaller - numbers raise the level of the sidelobes, increasing the likelihood - of frequency-domain interference, but allow the window to be shorter - in time. - */ - -void analyzer_setWindowWidth( double x ); -/* Set the frequency-domain main lobe width (measured between - zero-crossings) of the analysis window used by the Loris Analyzer. - */ - -void analyzer_storeResidueBandwidth( double regionWidth ); -/* Construct Partial bandwidth envelopes during analysis - by associating residual energy in the spectrum (after - peak extraction) with the selected spectral peaks that - are used to construct Partials. - - regionWidth is the width (in Hz) of the bandwidth - association regions used by this process, must be positive. - */ - -void analyzer_storeConvergenceBandwidth( double tolerancePct ); -/* Construct Partial bandwidth envelopes during analysis - by storing the mixed derivative of short-time phase, - scaled and shifted so that a value of 0 corresponds - to a pure sinusoid, and a value of 1 corresponds to a - bandwidth-enhanced sinusoid with maximal energy spread - (minimum sinusoidal convergence). - - tolerance is the amount of range over which the - mixed derivative indicator should be allowed to drift away - from a pure sinusoid before saturating. This range is mapped - to bandwidth values on the range [0,1]. Must be positive and - not greater than 1. - */ - -void analyzer_storeNoBandwidth( void ); -/* Disable bandwidth envelope construction. Bandwidth - will be zero for all Breakpoints in all Partials. - */ - -double analyzer_getBwRegionWidth( void ); -/* Return the width (in Hz) of the Bandwidth Association regions - used by this Analyzer, only if the spectral residue method is - used to compute bandwidth envelopes. Return zero if the mixed - derivative method is used, or if no bandwidth is computed. - */ - -double analyzer_getBwConvergenceTolerance( void ); -/* Return the mixed derivative convergence tolerance - only if the convergence indicator is used to compute - bandwidth envelopes. Return zero if the spectral residue - method is used or if no bandwidth is computed. - */ - - -/* ---------------------------------------------------------------- */ -/* LinearEnvelope object interface -/* -/* A LinearEnvelope represents a linear segment breakpoint - function with infinite extension at each end (that is, the - values past either end of the breakpoint function have the - values at the nearest end). - - In C++, a LinearEnvelope is a Loris::LinearEnvelope. - */ - -LinearEnvelope * createLinearEnvelope( void ); -/* Construct and return a new LinearEnvelope having no - breakpoints and an implicit value of 0. everywhere, - until the first breakpoint is inserted. - */ - -LinearEnvelope * copyLinearEnvelope( const LinearEnvelope * ptr_this ); -/* Construct and return a new LinearEnvelope that is an - exact copy of the specified LinearEnvelopes, having - an identical set of breakpoints. - */ - -void destroyLinearEnvelope( LinearEnvelope * ptr_this ); -/* Destroy this LinearEnvelope. - */ - -void linearEnvelope_insertBreakpoint( LinearEnvelope * ptr_this, - double time, double val ); -/* Insert a breakpoint representing the specified (time, value) - pair into this LinearEnvelope. If there is already a - breakpoint at the specified time, it will be replaced with - the new breakpoint. - */ - -double linearEnvelope_valueAt( const LinearEnvelope * ptr_this, - double time ); -/* Return the interpolated value of this LinearEnvelope at the - specified time. - */ - -/* ---------------------------------------------------------------- */ -/* PartialList object interface -/* -/* A PartialList represents a collection of Bandwidth-Enhanced - Partials, each having a trio of synchronous, non-uniformly- - sampled breakpoint envelopes representing the time-varying - frequency, amplitude, and noisiness of a single bandwidth- - enhanced sinusoid. - - For more information about Bandwidth-Enhanced Partials and the - Reassigned Bandwidth-Enhanced Additive Sound Model, refer to - the Loris website: www.cerlsoundgroup.org/Loris/. - - In C++, a PartialList is a Loris::PartialList. - */ -PartialList * createPartialList( void ); -/* Return a new empty PartialList. - */ - -void destroyPartialList( PartialList * ptr_this ); -/* Destroy this PartialList. - */ - -void partialList_clear( PartialList * ptr_this ); -/* Remove (and destroy) all the Partials from this PartialList, - leaving it empty. - */ - -void partialList_copy( PartialList * ptr_this, - const PartialList * src ); -/* Make this PartialList a copy of the source PartialList by making - copies of all of the Partials in the source and adding them to - this PartialList. - */ - -unsigned long partialList_size( const PartialList * ptr_this ); -/* Return the number of Partials in this PartialList. - */ - -void partialList_splice( PartialList * ptr_this, - PartialList * src ); -/* Splice all the Partials in the source PartialList onto the end of - this PartialList, leaving the source empty. - */ - -/* ---------------------------------------------------------------- */ -/* Partial object interface -/* -/* A Partial represents a single component in the - reassigned bandwidth-enhanced additive model. A Partial consists of a - chain of Breakpoints describing the time-varying frequency, amplitude, - and bandwidth (or noisiness) envelopes of the component, and a 4-byte - label. The Breakpoints are non-uniformly distributed in time. For more - information about Reassigned Bandwidth-Enhanced Analysis and the - Reassigned Bandwidth-Enhanced Additive Sound Model, refer to the Loris - website: www.cerlsoundgroup.org/Loris/. - */ - -double partial_startTime( const Partial * p ); -/* Return the start time (seconds) for the specified Partial. - */ - -double partial_endTime( const Partial * p ); -/* Return the end time (seconds) for the specified Partial. - */ - -double partial_duration( const Partial * p ); -/* Return the duration (seconds) for the specified Partial. - */ - -double partial_initialPhase( const Partial * p ); -/* Return the initial phase (radians) for the specified Partial. - */ - -int partial_label( const Partial * p ); -/* Return the integer label for the specified Partial. - */ - -unsigned long partial_numBreakpoints( const Partial * p ); -/* Return the number of Breakpoints in the specified Partial. - */ - -double partial_frequencyAt( const Partial * p, double t ); -/* Return the frequency (Hz) of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ - -double partial_bandwidthAt( const Partial * p, double t ); -/* Return the bandwidth of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ - -double partial_phaseAt( const Partial * p, double t ); -/* Return the phase (radians) of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ - -double partial_amplitudeAt( const Partial * p, double t ); -/* Return the (absolute) amplitude of the specified Partial interpolated - at a particular time. Partials are assumed to fade out - over 1 millisecond at the ends (rather than instantaneously). - It is an error to apply this function to a Partial having no Breakpoints. - */ - -void partial_setLabel( Partial * p, int label ); -/* Assign a new integer label to the specified Partial. - */ - -/* ---------------------------------------------------------------- */ -/* Breakpoint object interface -/* -/* A Breakpoint represents a single breakpoint in the - Partial parameter (frequency, amplitude, bandwidth) envelope. - Instantaneous phase is also stored, but is only used at the onset of - a partial, or when it makes a transition from zero to nonzero amplitude. - - Loris Partials represent reassigned bandwidth-enhanced model components. - A Partial consists of a chain of Breakpoints describing the time-varying - frequency, amplitude, and bandwidth (noisiness) of the component. - For more information about Reassigned Bandwidth-Enhanced - Analysis and the Reassigned Bandwidth-Enhanced Additive Sound - Model, refer to the Loris website: - www.cerlsoundgroup.org/Loris/. - */ - -double breakpoint_getAmplitude( const Breakpoint * bp ); -/* Return the (absolute) amplitude of the specified Breakpoint. - */ - -double breakpoint_getBandwidth( const Breakpoint * bp ); -/* Return the bandwidth coefficient of the specified Breakpoint. - */ - -double breakpoint_getFrequency( const Breakpoint * bp ); -/* Return the frequency (Hz) of the specified Breakpoint. - */ - -double breakpoint_getPhase( const Breakpoint * bp ); -/* Return the phase (radians) of the specified Breakpoint. - */ - -void breakpoint_setAmplitude( Breakpoint * bp, double a ); -/* Assign a new (absolute) amplitude to the specified Breakpoint. - */ - -void breakpoint_setBandwidth( Breakpoint * bp, double bw ); -/* Assign a new bandwidth coefficient to the specified Breakpoint. - */ - -void breakpoint_setFrequency( Breakpoint * bp, double f ); -/* Assign a new frequency (Hz) to the specified Breakpoint. - */ - -void breakpoint_setPhase( Breakpoint * bp, double phi ); -/* Assign a new phase (radians) to the specified Breakpoint. - */ - -/* ---------------------------------------------------------------- */ -/* non-object-based procedures -/* -/* Operations in Loris that need not be accessed though object - interfaces are represented as simple functions. - */ - -void channelize( PartialList * partials, - LinearEnvelope * refFreqEnvelope, int refLabel ); -/* Label Partials in a PartialList with the integer nearest to - the amplitude-weighted average ratio of their frequency envelope - to a reference frequency envelope. The frequency spectrum is - partitioned into non-overlapping channels whose time-varying - center frequencies track the reference frequency envelope. - The reference label indicates which channel's center frequency - is exactly equal to the reference envelope frequency, and other - channels' center frequencies are multiples of the reference - envelope frequency divided by the reference label. Each Partial - in the PartialList is labeled with the number of the channel - that best fits its frequency envelope. The quality of the fit - is evaluated at the breakpoints in the Partial envelope and - weighted by the amplitude at each breakpoint, so that high- - amplitude breakpoints contribute more to the channel decision. - Partials are labeled, but otherwise unmodified. In particular, - their frequencies are not modified in any way. - */ - -void collate( PartialList * partials ); -/* Collate unlabeled (zero-labeled) Partials into the smallest-possible - number of Partials that does not combine any overlapping Partials. - Collated Partials appear at the end of the sequence, after all - labeled Partials. - */ - -LinearEnvelope * -createFreqReference( PartialList * partials, - double minFreq, double maxFreq, long numSamps ); -/* Return a newly-constructed LinearEnvelope using the legacy - FrequencyReference class. The envelope will have approximately - the specified number of samples. The specified number of samples - must be greater than 1. Uses the FundamentalEstimator - (FundamentalFromPartials) class to construct an estimator of - fundamental frequency, configured to emulate the behavior of - the FrequencyReference class in Loris 1.4-1.5.2. If numSamps - is zero, construct the reference envelope from fundamental - estimates taken every five milliseconds. - - For simple sounds, this frequency reference may be a - good first approximation to a reference envelope for - channelization (see channelize()). - - Clients are responsible for disposing of the newly-constructed - LinearEnvelope. - */ - -LinearEnvelope * -createF0Estimate( PartialList * partials, double minFreq, double maxFreq, - double interval, void* threadController); -/* Return a newly-constructed LinearEnvelope that estimates - the time-varying fundamental frequency of the sound - represented by the Partials in a PartialList. This uses - the FundamentalEstimator (FundamentalFromPartials) - class to construct an estimator of fundamental frequency, - and returns a LinearEnvelope that samples the estimator at the - specified time interval (in seconds). Default values are used - to configure the estimator. Only estimates in the specified - frequency range will be considered valid, estimates outside this - range will be ignored. - - Clients are responsible for disposing of the newly-constructed - LinearEnvelope. - */ - -void dilate( PartialList * partials, - const double * initial, const double * target, int npts ); -/* Dilate Partials in a PartialList according to the given - initial and target time points. Partial envelopes are - stretched and compressed so that temporal features at - the initial time points are aligned with the final time - points. Time points are sorted, so Partial envelopes are - are only stretched and compressed, but breakpoints are not - reordered. Duplicate time points are allowed. There must be - the same number of initial and target time points. - */ - -void distill( PartialList * partials ); -/* Distill labeled (channelized) Partials in a PartialList into a - PartialList containing at most one Partial per label. Unlabeled - (zero-labeled) Partials are left unmodified at the end of the - distilled Partials. - */ - -void exportAiff( const char * path, const double * buffer, - unsigned int bufferSize, double samplerate, int bitsPerSamp ); -/* Export mono audio samples stored in an array of size bufferSize to - an AIFF file having the specified sample rate at the given file path - (or name). The floating point samples in the buffer are clamped to the - range (-1.,1.) and converted to integers having bitsPerSamp bits. - */ - -void exportSdif( const char * path, PartialList * partials ); -/* Export Partials in a PartialList to a SDIF file at the specified - file path (or name). SDIF data is described by RBEM and RBEL - matrices. - For more information about SDIF, see the SDIF web site at: - www.ircam.fr/equipes/analyse-synthese/sdif/ - */ - -void exportSpc( const char * path, PartialList * partials, double midiPitch, - int enhanced, double endApproachTime ); -/* Export Partials in a PartialList to a Spc file at the specified file - path (or name). The fractional MIDI pitch must be specified. The - enhanced parameter defaults to true (for bandwidth-enhanced spc files), - but an be specified false for pure-sines spc files. The endApproachTime - parameter is in seconds. A nonzero endApproachTime indicates that the plist does - not include a release, but rather ends in a static spectrum corresponding - to the final breakpoint values of the partials. The endApproachTime - specifies how long before the end of the sound the amplitude, frequency, - and bandwidth values are to be modified to make a gradual transition to - the static spectrum. - */ - -/* Apply a reference Partial to fix the frequencies of Breakpoints - whose amplitude is below threshold_dB. 0 harmonifies full-amplitude - Partials, to apply only to quiet Partials, specify a lower - threshold like -90). The reference Partial is the first Partial - in the PartialList labeled refLabel (usually 1). The LinearEnvelope - is a time-varying weighting on the harmonifing process. When 1, - harmonic frequencies are used, when 0, breakpoint frequencies are - unmodified. - */ -void harmonify( PartialList * partials, long refLabel, - const LinearEnvelope * env, double threshold_dB ); - -unsigned int importAiff( const char * path, double * buffer, unsigned int bufferSize, - double * samplerate ); -/* Import audio samples stored in an AIFF file at the given file - path (or name). The samples are converted to floating point - values on the range (-1.,1.) and stored in an array of doubles. - The value returned is the number of samples in buffer, and it is at - most bufferSize. If samplerate is not a NULL pointer, - then, on return, it points to the value of the sample rate (in - Hz) of the AIFF samples. The AIFF file must contain only a single - channel of audio data. The prior contents of buffer, if any, are - overwritten. - */ - -void importSdif( const char * path, PartialList * partials ); -/* Import Partials from an SDIF file at the given file path (or - name), and append them to a PartialList. - */ - -void importSpc( const char * path, PartialList * partials ); -/* Import Partials from an Spc file at the given file path (or - name), and return them in a PartialList. - */ - -void morph( const PartialList * src0, const PartialList * src1, - const LinearEnvelope * ffreq, - const LinearEnvelope * famp, - const LinearEnvelope * fbw, - PartialList * dst ); -/* Morph labeled Partials in two PartialLists according to the - given frequency, amplitude, and bandwidth (noisiness) morphing - envelopes, and append the morphed Partials to the destination - PartialList. Loris morphs Partials by interpolating frequency, - amplitude, and bandwidth envelopes of corresponding Partials in - the source PartialLists. For more information about the Loris - morphing algorithm, see the Loris website: - www.cerlsoundgroup.org/Loris/ - */ - -void morphWithReference( const PartialList * src0, - const PartialList * src1, - long src0RefLabel, - long src1RefLabel, - const LinearEnvelope * ffreq, - const LinearEnvelope * famp, - const LinearEnvelope * fbw, - PartialList * dst ); -/* Morph labeled Partials in two PartialLists according to the - given frequency, amplitude, and bandwidth (noisiness) morphing - envelopes, and append the morphed Partials to the destination - PartialList. Specify the labels of the Partials to be used as - reference Partial for the two morph sources. The reference - partial is used to compute frequencies for very low-amplitude - Partials whose frequency estimates are not considered reliable. - The reference Partial is considered to have good frequency - estimates throughout. A reference label of 0 indicates that - no reference Partial should be used for the corresponding - morph source. - - Loris morphs Partials by interpolating frequency, - amplitude, and bandwidth envelopes of corresponding Partials in - the source PartialLists. For more information about the Loris - morphing algorithm, see the Loris website: - www.cerlsoundgroup.org/Loris/ - */ - -void morpher_setAmplitudeShape( double shape ); -/* Set the shaping parameter for the amplitude morphing - function. This shaping parameter controls the slope of - the amplitude morphing function, for values greater than - 1, this function gets nearly linear (like the old - amplitude morphing function), for values much less than - 1 (e.g. 1E-5) the slope is gently curved and sounds - pretty "linear", for very small values (e.g. 1E-12) the - curve is very steep and sounds un-natural because of the - huge jump from zero amplitude to very small amplitude. - - Use LORIS_DEFAULT_AMPMORPHSHAPE to obtain the default - amplitude morphing shape for Loris, (equal to 1E-5, - which works well for many musical instrument morphs, - unless Loris was compiled with the symbol - LINEAR_AMP_MORPHS defined, in which case - LORIS_DEFAULT_AMPMORPHSHAPE is equal to - LORIS_LINEAR_AMPMORPHSHAPE). - - Use LORIS_LINEAR_AMPMORPHSHAPE to approximate the linear - amplitude morphs performed by older versions of Loris. - - The amplitude shape must be positive. - */ - -extern const double LORIS_DEFAULT_AMPMORPHSHAPE; -extern const double LORIS_LINEAR_AMPMORPHSHAPE; - -void resample( PartialList * partials, double interval ); -/* Resample all Partials in a PartialList using the specified - sampling interval, so that the Breakpoints in the Partial - envelopes will all lie on a common temporal grid. - The Breakpoint times in resampled Partials will comprise a - contiguous sequence of integer multiples of the sampling interval, - beginning with the multiple nearest to the Partial's start time and - ending with the multiple nearest to the Partial's end time. Resampling - is performed in-place. - - */ - -void shapeSpectrum( PartialList * partials, PartialList * surface, - double stretchFreq, double stretchTime ); -/* Scale the amplitudes of a set of Partials by applying - a spectral suface constructed from another set. - Stretch the spectral surface in time and frequency - using the specified stretch factors. Set the stretch - factors to one for no stretching. - */ - -void sift( PartialList * partials ); -/* Identify overlapping Partials having the same (nonzero) - label. If any two partials with same label - overlap in time, set the label of the weaker - (having less total energy) partial to zero. - - */ - -unsigned int -synthesize( const PartialList * partials, - double * buffer, unsigned int bufferSize, - double srate ); -/* Synthesize Partials in a PartialList at the given sample - rate, and store the (floating point) samples in a buffer of - size bufferSize. The buffer is neither resized nor - cleared before synthesis, so newly synthesized samples are - added to any previously computed samples in the buffer, and - samples beyond the end of the buffer are lost. Return the - number of samples synthesized, that is, the index of the - latest sample in the buffer that was modified. - */ - -/* ---------------------------------------------------------------- */ -/* utility functions -/* -/* Operations for transforming and manipulating collections - of Partials. - */ - -double avgAmplitude( const Partial * p ); -/* Return the average amplitude over all Breakpoints in this Partial. - Return zero if the Partial has no Breakpoints. - */ - -double avgFrequency( const Partial * p ); -/* Return the average frequency over all Breakpoints in this Partial. - Return zero if the Partial has no Breakpoints. - */ - -void copyIf( const PartialList * src, PartialList * dst, - int ( * predicate )( const Partial * p, void * data ), - void * data ); -/* Append copies of Partials in the source PartialList satisfying the - specified predicate to the destination PartialList. The source list - is unmodified. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ - -void copyLabeled( const PartialList * src, long label, PartialList * dst ); -/* Append copies of Partials in the source PartialList having the - specified label to the destination PartialList. The source list - is unmodified. - */ - -void crop( PartialList * partials, double t1, double t2 ); -/* Trim Partials by removing Breakpoints outside a specified time span. - Insert a Breakpoint at the boundary when cropping occurs. Remove - any Partials that are left empty after cropping (Partials having no - Breakpoints between t1 and t2). - */ - -void extractIf( PartialList * src, PartialList * dst, - int ( * predicate )( const Partial * p, void * data ), - void * data ); -/* Remove Partials in the source PartialList satisfying the - specified predicate from the source list and append them to - the destination PartialList. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ - -void extractLabeled( PartialList * src, long label, PartialList * dst ); -/* Remove Partials in the source PartialList having the specified - label from the source list and append them to the destination - PartialList. - */ - -void fixPhaseAfter( PartialList * partials, double time ); -/* Recompute phases of all Breakpoints later than the specified - time so that the synthesized phases of those later Breakpoints - matches the stored phase, as long as the synthesized phase at - the specified time matches the stored (not recomputed) phase. - - Phase fixing is only applied to non-null (nonzero-amplitude) - Breakpoints, because null Breakpoints are interpreted as phase - reset points in Loris. If a null is encountered, its phase is - corrected from its non-Null successor, if it has one, otherwise - it is unmodified. - */ - -void fixPhaseAt( PartialList * partials, double time ); -/* Recompute phases of all Breakpoints in a Partial - so that the synthesized phases match the stored phases, - and the synthesized phase at (nearest) the specified - time matches the stored (not recomputed) phase. - - Backward phase-fixing stops if a null (zero-amplitude) - Breakpoint is encountered, because nulls are interpreted as - phase reset points in Loris. If a null is encountered, the - remainder of the Partial (the front part) is fixed in the - forward direction, beginning at the start of the Partial. - Forward phase fixing is only applied to non-null - (nonzero-amplitude) Breakpoints. If a null is encountered, - its phase is corrected from its non-Null successor, if - it has one, otherwise it is unmodified. - */ - -void fixPhaseBefore( PartialList * partials, double time ); -/* Recompute phases of all Breakpoints earlier than the specified - time so that the synthesized phases of those earlier Breakpoints - matches the stored phase, and the synthesized phase at the - specified time matches the stored (not recomputed) phase. - - Backward phase-fixing stops if a null (zero-amplitude) Breakpoint - is encountered, because nulls are interpreted as phase reset - points in Loris. If a null is encountered, the remainder of the - Partial (the front part) is fixed in the forward direction, - beginning at the start of the Partial. - */ - -void fixPhaseBetween( PartialList * partials, double tbeg, double tend ); -/* - Fix the phase travel between two times by adjusting the - frequency and phase of Breakpoints between those two times. - - This algorithm assumes that there is nothing interesting - about the phases of the intervening Breakpoints, and modifies - their frequencies as little as possible to achieve the correct - amount of phase travel such that the frequencies and phases at - the specified times match the stored values. The phases of all - the Breakpoints between the specified times are recomputed. - */ - -void fixPhaseForward( PartialList * partials, double tbeg, double tend ); -/* Recompute phases of all Breakpoints later than the specified - time so that the synthesized phases of those later Breakpoints - matches the stored phase, as long as the synthesized phase at - the specified time matches the stored (not recomputed) phase. - Breakpoints later than tend are unmodified. - - Phase fixing is only applied to non-null (nonzero-amplitude) - Breakpoints, because null Breakpoints are interpreted as phase - reset points in Loris. If a null is encountered, its phase is - corrected from its non-Null successor, if it has one, otherwise - it is unmodified. - */ - -int forEachBreakpoint( Partial * p, - int ( * func )( Breakpoint * p, double time, void * data ), - void * data ); -/* Apply a function to each Breakpoint in a Partial. The function - is called once for each Breakpoint in the source Partial. The - function may modify the Breakpoint (but should not otherwise attempt - to modify the Partial). The data parameter can be used to supply extra - user-defined data to the function. Pass 0 if no additional data is needed. - The function should return 0 if successful. If the function returns - a non-zero value, then forEachBreakpoint immediately returns that value - without applying the function to any other Breakpoints in the Partial. - forEachBreakpoint returns zero if all calls to func return zero. - */ - -int forEachPartial( PartialList * src, - int ( * func )( Partial * p, void * data ), - void * data ); -/* Apply a function to each Partial in a PartialList. The function - is called once for each Partial in the source PartialList. The - function may modify the Partial (but should not attempt to modify - the PartialList). The data parameter can be used to supply extra - user-defined data to the function. Pass 0 if no additional data - is needed. The function should return 0 if successful. If the - function returns a non-zero value, then forEachPartial immediately - returns that value without applying the function to any other - Partials in the PartialList. forEachPartial returns zero if all - calls to func return zero. - */ - -double peakAmplitude( const Partial * p ); -/* Return the maximum amplitude achieved by a Partial. - */ - -void removeIf( PartialList * src, - int ( * predicate )( const Partial * p, void * data ), - void * data ); -/* Remove from a PartialList all Partials satisfying the - specified predicate. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ - -void removeLabeled( PartialList * src, long label ); -/* Remove from a PartialList all Partials having the specified label. - */ - -void scaleAmplitude( PartialList * partials, LinearEnvelope * ampEnv ); -/* Scale the amplitude of the Partials in a PartialList according - to an envelope representing a time-varying amplitude scale value. - */ - -void scaleAmp( PartialList * partials, LinearEnvelope * ampEnv ); -/* Bad old name for scaleAmplitude. - */ - -void scaleBandwidth( PartialList * partials, LinearEnvelope * bwEnv ); -/* Scale the bandwidth of the Partials in a PartialList according - to an envelope representing a time-varying bandwidth scale value. - */ - -void scaleFrequency( PartialList * partials, LinearEnvelope * freqEnv ); -/* Scale the frequency of the Partials in a PartialList according - to an envelope representing a time-varying frequency scale value. - */ - -void scaleNoiseRatio( PartialList * partials, LinearEnvelope * noiseEnv ); -/* Scale the relative noise content of the Partials in a PartialList - according to an envelope representing a (time-varying) noise energy - scale value. - */ - -void setBandwidth( PartialList * partials, LinearEnvelope * bwEnv ); -/* Set the bandwidth of the Partials in a PartialList according - to an envelope representing a time-varying bandwidth value. - */ - -void shiftPitch( PartialList * partials, LinearEnvelope * pitchEnv ); -/* Shift the pitch of all Partials in a PartialList according to - the given pitch envelope. The pitch envelope is assumed to have - units of cents (1/100 of a halfstep). - */ - -void shiftTime( PartialList * partials, double offset ); -/* Shift the time of all the Breakpoints in a Partial by a - constant amount. - */ - -void sortByLabel( PartialList * partials ); -/* Sort the Partials in a PartialList in order of increasing label. - The sort is stable; Partials having the same label are not - reordered. - */ - -void timeSpan( PartialList * partials, double * tmin, double * tmax ); -/* Return the minimum start time and maximum end time - in seconds of all Partials in this PartialList. The v - times are returned in the (non-null) pointers tmin - and tmax. - */ - -double weightedAvgFrequency( const Partial * p ); -/* Return the average frequency over all Breakpoints in this Partial, - weighted by the Breakpoint amplitudes. Return zero if the Partial - has no Breakpoints. - */ - -/* ---------------------------------------------------------------- */ -/* Notification and exception handlers -/* -/* An exception handler and a notifier may be specified. Both - are functions taking a const char * argument and returning - void. - */ - -void setExceptionHandler( void(*f)(const char *) ); -/* Specify a function to call when reporting exceptions. The - function takes a const char * argument, and returns void. - */ - -void setNotifier( void(*f)(const char *) ); -/* Specify a notification function. The function takes a - const char * argument, and returns void. - */ - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -#endif /* ndef INCLUDE_LORIS_H */ diff --git a/loris_library/Source/src/loris.h.in b/loris_library/Source/src/loris.h.in deleted file mode 100644 index 9948da3..0000000 --- a/loris_library/Source/src/loris.h.in +++ /dev/null @@ -1,1020 +0,0 @@ -#ifndef INCLUDE_LORIS_H -#define INCLUDE_LORIS_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * loris.h - * - * Header specifying C-linkable procedural interface for Loris. - * - * Main components of this interface: - * - version identification symbols - * - type declarations - * - Analyzer configuration - * - LinearEnvelope (formerly BreakpointEnvelope) operations - * - PartialList operations - * - Partial operations - * - Breakpoint operations - * - sound modeling functions for preparing PartialLists - * - utility functions for manipulating PartialLists - * - notification and exception handlers (all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function. The default one in Loris uses printf()). - * - * loris.h is generated automatically from loris.h.in. Do not modify loris.h - * - * Kelly Fitz, 4 Feb 2002 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -/* ---------------------------------------------------------------- */ -/* Version -/* -/* Define symbols that facilitate version/release identification. - */ - -#define LORIS_MAJOR_VERSION @LORIS_MAJOR_VERSION@ -#define LORIS_MINOR_VERSION @LORIS_MINOR_VERSION@ -#define LORIS_SUBMINOR_VERSION @LORIS_SUBMINOR_VERSION@ -#define LORIS_VERSION_STR "@LORIS_VERSION_STR@" - -/* ---------------------------------------------------------------- */ -/* Types -/* -/* The (class) types Breakpoint, LinearEnvelope, Partial, - and PartialList are imported from the Loris namespace. - The first three are classes, the latter is a typedef - for std::list< Loris::Partial >. - */ -#if defined(__cplusplus) - // include std library list header, declaring templates - // is too painful and fragile: - #include - - // declare Loris classes in Loris namespace: - namespace Loris - { - class Breakpoint; - class LinearEnvelope; - class Partial; - - // this typedef has to be copied from PartialList.h - typedef std::list< Loris::Partial > PartialList; - } - - // import those names into the global namespace - using Loris::Breakpoint; - using Loris::LinearEnvelope; - using Loris::Partial; - using Loris::PartialList; -#else - /* no classes, just declare types and use - opaque C pointers - */ - typedef struct Breakpoint Breakpoint; - typedef struct LinearEnvelope LinearEnvelope; - typedef struct PartialList PartialList; - typedef struct Partial Partial; -#endif - -/* - TODO - Maybe should also have loris_label_t and loris_size_t - defined, depending on configure. -*/ - -#if defined(__cplusplus) - extern "C" { -#endif - -/* ---------------------------------------------------------------- */ -/* Analyzer configuration -/* -/* An Analyzer represents a configuration of parameters for - performing Reassigned Bandwidth-Enhanced Additive Analysis - of sampled waveforms. This analysis process yields a collection - of Partials, each having a trio of synchronous, non-uniformly- - sampled breakpoint envelopes representing the time-varying - frequency, amplitude, and noisiness of a single bandwidth- - enhanced sinusoid. - - For more information about Reassigned Bandwidth-Enhanced - Analysis and the Reassigned Bandwidth-Enhanced Additive Sound - Model, refer to the Loris website: www.cerlsoundgroup.org/Loris/. - - In the procedural interface, there is only one Analyzer. - It must be configured by calling analyzer_configure before - any of the other analyzer operations can be performed. - */ - -void analyze( const double * buffer, unsigned int bufferSize, - double srate, PartialList * partials ); -/* Analyze an array of bufferSize (mono) samples at the given sample rate - (in Hz) and append the extracted Partials to the given - PartialList. - */ - -void analyzer_configure( double resolution, double windowWidth ); -/* Configure the sole Analyzer instance with the specified - frequency resolution (minimum instantaneous frequency - difference between Partials). All other Analyzer parameters - are computed from the specified frequency resolution. - - Construct the Analyzer instance if necessary. - - In the procedural interface, there is only one Analyzer. - It must be configured by calling analyzer_configure before - any of the other analyzer operations can be performed. - */ - -double analyzer_getAmpFloor( void ); -/* Return the amplitude floor (lowest detected spectral amplitude), - in (negative) dB, for the Loris Analyzer. - */ - -double analyzer_getCropTime( void ); -/* Return the crop time (maximum temporal displacement of a time- - frequency data point from the time-domain center of the analysis - window, beyond which data points are considered "unreliable") - for the Loris Analyzer. - */ - -double analyzer_getFreqDrift( void ); -/* Return the maximum allowable frequency difference between - consecutive Breakpoints in a Partial envelope for the Loris Analyzer. - */ - -double analyzer_getFreqFloor( void ); -/* Return the frequency floor (minimum instantaneous Partial - frequency), in Hz, for the Loris Analyzer. - */ - -double analyzer_getFreqResolution( void ); -/* Return the frequency resolution (minimum instantaneous frequency - difference between Partials) for the Loris Analyzer. - */ - -double analyzer_getHopTime( void ); -/* Return the hop time (which corresponds approximately to the - average density of Partial envelope Breakpoint data) for this - Analyzer. - */ - -double analyzer_getSidelobeLevel( void ); -/* Return the sidelobe attenutation level for the Kaiser analysis window in - positive dB. Higher numbers (e.g. 90) give very good sidelobe - rejection but cause the window to be longer in time. Smaller - numbers raise the level of the sidelobes, increasing the likelihood - of frequency-domain interference, but allow the window to be shorter - in time. - */ - -double analyzer_getWindowWidth( void ); -/* Return the frequency-domain main lobe width (measured between - zero-crossings) of the analysis window used by the Loris Analyzer. - */ - -void analyzer_setAmpFloor( double x ); -/* Set the amplitude floor (lowest detected spectral amplitude), in - (negative) dB, for the Loris Analyzer. - */ - -void analyzer_setBwRegionWidth( double x ); -/* Deprecated, use analyzer_storeResidueBandwidth instead. - */ - -void analyzer_setCropTime( double x ); -/* Set the crop time (maximum temporal displacement of a time- - frequency data point from the time-domain center of the analysis - window, beyond which data points are considered "unreliable") - for the Loris Analyzer. - */ - -void analyzer_setFreqDrift( double x ); -/* Set the maximum allowable frequency difference between - consecutive Breakpoints in a Partial envelope for the Loris Analyzer. - */ - -void analyzer_setFreqFloor( double x ); -/* Set the amplitude floor (minimum instantaneous Partial - frequency), in Hz, for the Loris Analyzer. - */ - -void analyzer_setFreqResolution( double x ); -/* Set the frequency resolution (minimum instantaneous frequency - difference between Partials) for the Loris Analyzer. (Does not cause - other parameters to be recomputed.) - */ - -void analyzer_setHopTime( double x ); -/* Set the hop time (which corresponds approximately to the average - density of Partial envelope Breakpoint data) for the Loris Analyzer. - */ - -void analyzer_setSidelobeLevel( double x ); -/* Set the sidelobe attenutation level for the Kaiser analysis window in - positive dB. Larger numbers (e.g. 90) give very good sidelobe - rejection but cause the window to be longer in time. Smaller - numbers raise the level of the sidelobes, increasing the likelihood - of frequency-domain interference, but allow the window to be shorter - in time. - */ - -void analyzer_setWindowWidth( double x ); -/* Set the frequency-domain main lobe width (measured between - zero-crossings) of the analysis window used by the Loris Analyzer. - */ - -void analyzer_storeResidueBandwidth( double regionWidth ); -/* Construct Partial bandwidth envelopes during analysis - by associating residual energy in the spectrum (after - peak extraction) with the selected spectral peaks that - are used to construct Partials. - - regionWidth is the width (in Hz) of the bandwidth - association regions used by this process, must be positive. - */ - -void analyzer_storeConvergenceBandwidth( double tolerancePct ); -/* Construct Partial bandwidth envelopes during analysis - by storing the mixed derivative of short-time phase, - scaled and shifted so that a value of 0 corresponds - to a pure sinusoid, and a value of 1 corresponds to a - bandwidth-enhanced sinusoid with maximal energy spread - (minimum sinusoidal convergence). - - tolerance is the amount of range over which the - mixed derivative indicator should be allowed to drift away - from a pure sinusoid before saturating. This range is mapped - to bandwidth values on the range [0,1]. Must be positive and - not greater than 1. - */ - -void analyzer_storeNoBandwidth( void ); -/* Disable bandwidth envelope construction. Bandwidth - will be zero for all Breakpoints in all Partials. - */ - -double analyzer_getBwRegionWidth( void ); -/* Return the width (in Hz) of the Bandwidth Association regions - used by this Analyzer, only if the spectral residue method is - used to compute bandwidth envelopes. Return zero if the mixed - derivative method is used, or if no bandwidth is computed. - */ - -double analyzer_getBwConvergenceTolerance( void ); -/* Return the mixed derivative convergence tolerance - only if the convergence indicator is used to compute - bandwidth envelopes. Return zero if the spectral residue - method is used or if no bandwidth is computed. - */ - - -/* ---------------------------------------------------------------- */ -/* LinearEnvelope object interface -/* -/* A LinearEnvelope represents a linear segment breakpoint - function with infinite extension at each end (that is, the - values past either end of the breakpoint function have the - values at the nearest end). - - In C++, a LinearEnvelope is a Loris::LinearEnvelope. - */ - -LinearEnvelope * createLinearEnvelope( void ); -/* Construct and return a new LinearEnvelope having no - breakpoints and an implicit value of 0. everywhere, - until the first breakpoint is inserted. - */ - -LinearEnvelope * copyLinearEnvelope( const LinearEnvelope * ptr_this ); -/* Construct and return a new LinearEnvelope that is an - exact copy of the specified LinearEnvelopes, having - an identical set of breakpoints. - */ - -void destroyLinearEnvelope( LinearEnvelope * ptr_this ); -/* Destroy this LinearEnvelope. - */ - -void linearEnvelope_insertBreakpoint( LinearEnvelope * ptr_this, - double time, double val ); -/* Insert a breakpoint representing the specified (time, value) - pair into this LinearEnvelope. If there is already a - breakpoint at the specified time, it will be replaced with - the new breakpoint. - */ - -double linearEnvelope_valueAt( const LinearEnvelope * ptr_this, - double time ); -/* Return the interpolated value of this LinearEnvelope at the - specified time. - */ - -/* ---------------------------------------------------------------- */ -/* PartialList object interface -/* -/* A PartialList represents a collection of Bandwidth-Enhanced - Partials, each having a trio of synchronous, non-uniformly- - sampled breakpoint envelopes representing the time-varying - frequency, amplitude, and noisiness of a single bandwidth- - enhanced sinusoid. - - For more information about Bandwidth-Enhanced Partials and the - Reassigned Bandwidth-Enhanced Additive Sound Model, refer to - the Loris website: www.cerlsoundgroup.org/Loris/. - - In C++, a PartialList is a Loris::PartialList. - */ -PartialList * createPartialList( void ); -/* Return a new empty PartialList. - */ - -void destroyPartialList( PartialList * ptr_this ); -/* Destroy this PartialList. - */ - -void partialList_clear( PartialList * ptr_this ); -/* Remove (and destroy) all the Partials from this PartialList, - leaving it empty. - */ - -void partialList_copy( PartialList * ptr_this, - const PartialList * src ); -/* Make this PartialList a copy of the source PartialList by making - copies of all of the Partials in the source and adding them to - this PartialList. - */ - -unsigned long partialList_size( const PartialList * ptr_this ); -/* Return the number of Partials in this PartialList. - */ - -void partialList_splice( PartialList * ptr_this, - PartialList * src ); -/* Splice all the Partials in the source PartialList onto the end of - this PartialList, leaving the source empty. - */ - -/* ---------------------------------------------------------------- */ -/* Partial object interface -/* -/* A Partial represents a single component in the - reassigned bandwidth-enhanced additive model. A Partial consists of a - chain of Breakpoints describing the time-varying frequency, amplitude, - and bandwidth (or noisiness) envelopes of the component, and a 4-byte - label. The Breakpoints are non-uniformly distributed in time. For more - information about Reassigned Bandwidth-Enhanced Analysis and the - Reassigned Bandwidth-Enhanced Additive Sound Model, refer to the Loris - website: www.cerlsoundgroup.org/Loris/. - */ - -double partial_startTime( const Partial * p ); -/* Return the start time (seconds) for the specified Partial. - */ - -double partial_endTime( const Partial * p ); -/* Return the end time (seconds) for the specified Partial. - */ - -double partial_duration( const Partial * p ); -/* Return the duration (seconds) for the specified Partial. - */ - -double partial_initialPhase( const Partial * p ); -/* Return the initial phase (radians) for the specified Partial. - */ - -int partial_label( const Partial * p ); -/* Return the integer label for the specified Partial. - */ - -unsigned long partial_numBreakpoints( const Partial * p ); -/* Return the number of Breakpoints in the specified Partial. - */ - -double partial_frequencyAt( const Partial * p, double t ); -/* Return the frequency (Hz) of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ - -double partial_bandwidthAt( const Partial * p, double t ); -/* Return the bandwidth of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ - -double partial_phaseAt( const Partial * p, double t ); -/* Return the phase (radians) of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ - -double partial_amplitudeAt( const Partial * p, double t ); -/* Return the (absolute) amplitude of the specified Partial interpolated - at a particular time. Partials are assumed to fade out - over 1 millisecond at the ends (rather than instantaneously). - It is an error to apply this function to a Partial having no Breakpoints. - */ - -void partial_setLabel( Partial * p, int label ); -/* Assign a new integer label to the specified Partial. - */ - -/* ---------------------------------------------------------------- */ -/* Breakpoint object interface -/* -/* A Breakpoint represents a single breakpoint in the - Partial parameter (frequency, amplitude, bandwidth) envelope. - Instantaneous phase is also stored, but is only used at the onset of - a partial, or when it makes a transition from zero to nonzero amplitude. - - Loris Partials represent reassigned bandwidth-enhanced model components. - A Partial consists of a chain of Breakpoints describing the time-varying - frequency, amplitude, and bandwidth (noisiness) of the component. - For more information about Reassigned Bandwidth-Enhanced - Analysis and the Reassigned Bandwidth-Enhanced Additive Sound - Model, refer to the Loris website: - www.cerlsoundgroup.org/Loris/. - */ - -double breakpoint_getAmplitude( const Breakpoint * bp ); -/* Return the (absolute) amplitude of the specified Breakpoint. - */ - -double breakpoint_getBandwidth( const Breakpoint * bp ); -/* Return the bandwidth coefficient of the specified Breakpoint. - */ - -double breakpoint_getFrequency( const Breakpoint * bp ); -/* Return the frequency (Hz) of the specified Breakpoint. - */ - -double breakpoint_getPhase( const Breakpoint * bp ); -/* Return the phase (radians) of the specified Breakpoint. - */ - -void breakpoint_setAmplitude( Breakpoint * bp, double a ); -/* Assign a new (absolute) amplitude to the specified Breakpoint. - */ - -void breakpoint_setBandwidth( Breakpoint * bp, double bw ); -/* Assign a new bandwidth coefficient to the specified Breakpoint. - */ - -void breakpoint_setFrequency( Breakpoint * bp, double f ); -/* Assign a new frequency (Hz) to the specified Breakpoint. - */ - -void breakpoint_setPhase( Breakpoint * bp, double phi ); -/* Assign a new phase (radians) to the specified Breakpoint. - */ - -/* ---------------------------------------------------------------- */ -/* non-object-based procedures -/* -/* Operations in Loris that need not be accessed though object - interfaces are represented as simple functions. - */ - -void channelize( PartialList * partials, - LinearEnvelope * refFreqEnvelope, int refLabel ); -/* Label Partials in a PartialList with the integer nearest to - the amplitude-weighted average ratio of their frequency envelope - to a reference frequency envelope. The frequency spectrum is - partitioned into non-overlapping channels whose time-varying - center frequencies track the reference frequency envelope. - The reference label indicates which channel's center frequency - is exactly equal to the reference envelope frequency, and other - channels' center frequencies are multiples of the reference - envelope frequency divided by the reference label. Each Partial - in the PartialList is labeled with the number of the channel - that best fits its frequency envelope. The quality of the fit - is evaluated at the breakpoints in the Partial envelope and - weighted by the amplitude at each breakpoint, so that high- - amplitude breakpoints contribute more to the channel decision. - Partials are labeled, but otherwise unmodified. In particular, - their frequencies are not modified in any way. - */ - -void collate( PartialList * partials ); -/* Collate unlabeled (zero-labeled) Partials into the smallest-possible - number of Partials that does not combine any overlapping Partials. - Collated Partials appear at the end of the sequence, after all - labeled Partials. - */ - -LinearEnvelope * -createFreqReference( PartialList * partials, - double minFreq, double maxFreq, long numSamps ); -/* Return a newly-constructed LinearEnvelope using the legacy - FrequencyReference class. The envelope will have approximately - the specified number of samples. The specified number of samples - must be greater than 1. Uses the FundamentalEstimator - (FundamentalFromPartials) class to construct an estimator of - fundamental frequency, configured to emulate the behavior of - the FrequencyReference class in Loris 1.4-1.5.2. If numSamps - is zero, construct the reference envelope from fundamental - estimates taken every five milliseconds. - - For simple sounds, this frequency reference may be a - good first approximation to a reference envelope for - channelization (see channelize()). - - Clients are responsible for disposing of the newly-constructed - LinearEnvelope. - */ - -LinearEnvelope * -createF0Estimate( PartialList * partials, double minFreq, double maxFreq, - double interval ); -/* Return a newly-constructed LinearEnvelope that estimates - the time-varying fundamental frequency of the sound - represented by the Partials in a PartialList. This uses - the FundamentalEstimator (FundamentalFromPartials) - class to construct an estimator of fundamental frequency, - and returns a LinearEnvelope that samples the estimator at the - specified time interval (in seconds). Default values are used - to configure the estimator. Only estimates in the specified - frequency range will be considered valid, estimates outside this - range will be ignored. - - Clients are responsible for disposing of the newly-constructed - LinearEnvelope. - */ - -void dilate( PartialList * partials, - const double * initial, const double * target, int npts ); -/* Dilate Partials in a PartialList according to the given - initial and target time points. Partial envelopes are - stretched and compressed so that temporal features at - the initial time points are aligned with the final time - points. Time points are sorted, so Partial envelopes are - are only stretched and compressed, but breakpoints are not - reordered. Duplicate time points are allowed. There must be - the same number of initial and target time points. - */ - -void distill( PartialList * partials ); -/* Distill labeled (channelized) Partials in a PartialList into a - PartialList containing at most one Partial per label. Unlabeled - (zero-labeled) Partials are left unmodified at the end of the - distilled Partials. - */ - -void exportAiff( const char * path, const double * buffer, - unsigned int bufferSize, double samplerate, int bitsPerSamp ); -/* Export mono audio samples stored in an array of size bufferSize to - an AIFF file having the specified sample rate at the given file path - (or name). The floating point samples in the buffer are clamped to the - range (-1.,1.) and converted to integers having bitsPerSamp bits. - */ - -void exportSdif( const char * path, PartialList * partials ); -/* Export Partials in a PartialList to a SDIF file at the specified - file path (or name). SDIF data is described by RBEM and RBEL - matrices. - For more information about SDIF, see the SDIF web site at: - www.ircam.fr/equipes/analyse-synthese/sdif/ - */ - -void exportSpc( const char * path, PartialList * partials, double midiPitch, - int enhanced, double endApproachTime ); -/* Export Partials in a PartialList to a Spc file at the specified file - path (or name). The fractional MIDI pitch must be specified. The - enhanced parameter defaults to true (for bandwidth-enhanced spc files), - but an be specified false for pure-sines spc files. The endApproachTime - parameter is in seconds. A nonzero endApproachTime indicates that the plist does - not include a release, but rather ends in a static spectrum corresponding - to the final breakpoint values of the partials. The endApproachTime - specifies how long before the end of the sound the amplitude, frequency, - and bandwidth values are to be modified to make a gradual transition to - the static spectrum. - */ - -/* Apply a reference Partial to fix the frequencies of Breakpoints - whose amplitude is below threshold_dB. 0 harmonifies full-amplitude - Partials, to apply only to quiet Partials, specify a lower - threshold like -90). The reference Partial is the first Partial - in the PartialList labeled refLabel (usually 1). The LinearEnvelope - is a time-varying weighting on the harmonifing process. When 1, - harmonic frequencies are used, when 0, breakpoint frequencies are - unmodified. - */ -void harmonify( PartialList * partials, long refLabel, - const LinearEnvelope * env, double threshold_dB ); - -unsigned int importAiff( const char * path, double * buffer, unsigned int bufferSize, - double * samplerate ); -/* Import audio samples stored in an AIFF file at the given file - path (or name). The samples are converted to floating point - values on the range (-1.,1.) and stored in an array of doubles. - The value returned is the number of samples in buffer, and it is at - most bufferSize. If samplerate is not a NULL pointer, - then, on return, it points to the value of the sample rate (in - Hz) of the AIFF samples. The AIFF file must contain only a single - channel of audio data. The prior contents of buffer, if any, are - overwritten. - */ - -void importSdif( const char * path, PartialList * partials ); -/* Import Partials from an SDIF file at the given file path (or - name), and append them to a PartialList. - */ - -void importSpc( const char * path, PartialList * partials ); -/* Import Partials from an Spc file at the given file path (or - name), and return them in a PartialList. - */ - -void morph( const PartialList * src0, const PartialList * src1, - const LinearEnvelope * ffreq, - const LinearEnvelope * famp, - const LinearEnvelope * fbw, - PartialList * dst ); -/* Morph labeled Partials in two PartialLists according to the - given frequency, amplitude, and bandwidth (noisiness) morphing - envelopes, and append the morphed Partials to the destination - PartialList. Loris morphs Partials by interpolating frequency, - amplitude, and bandwidth envelopes of corresponding Partials in - the source PartialLists. For more information about the Loris - morphing algorithm, see the Loris website: - www.cerlsoundgroup.org/Loris/ - */ - -void morphWithReference( const PartialList * src0, - const PartialList * src1, - long src0RefLabel, - long src1RefLabel, - const LinearEnvelope * ffreq, - const LinearEnvelope * famp, - const LinearEnvelope * fbw, - PartialList * dst ); -/* Morph labeled Partials in two PartialLists according to the - given frequency, amplitude, and bandwidth (noisiness) morphing - envelopes, and append the morphed Partials to the destination - PartialList. Specify the labels of the Partials to be used as - reference Partial for the two morph sources. The reference - partial is used to compute frequencies for very low-amplitude - Partials whose frequency estimates are not considered reliable. - The reference Partial is considered to have good frequency - estimates throughout. A reference label of 0 indicates that - no reference Partial should be used for the corresponding - morph source. - - Loris morphs Partials by interpolating frequency, - amplitude, and bandwidth envelopes of corresponding Partials in - the source PartialLists. For more information about the Loris - morphing algorithm, see the Loris website: - www.cerlsoundgroup.org/Loris/ - */ - -void morpher_setAmplitudeShape( double shape ); -/* Set the shaping parameter for the amplitude morphing - function. This shaping parameter controls the slope of - the amplitude morphing function, for values greater than - 1, this function gets nearly linear (like the old - amplitude morphing function), for values much less than - 1 (e.g. 1E-5) the slope is gently curved and sounds - pretty "linear", for very small values (e.g. 1E-12) the - curve is very steep and sounds un-natural because of the - huge jump from zero amplitude to very small amplitude. - - Use LORIS_DEFAULT_AMPMORPHSHAPE to obtain the default - amplitude morphing shape for Loris, (equal to 1E-5, - which works well for many musical instrument morphs, - unless Loris was compiled with the symbol - LINEAR_AMP_MORPHS defined, in which case - LORIS_DEFAULT_AMPMORPHSHAPE is equal to - LORIS_LINEAR_AMPMORPHSHAPE). - - Use LORIS_LINEAR_AMPMORPHSHAPE to approximate the linear - amplitude morphs performed by older versions of Loris. - - The amplitude shape must be positive. - */ - -extern const double LORIS_DEFAULT_AMPMORPHSHAPE; -extern const double LORIS_LINEAR_AMPMORPHSHAPE; - -void resample( PartialList * partials, double interval ); -/* Resample all Partials in a PartialList using the specified - sampling interval, so that the Breakpoints in the Partial - envelopes will all lie on a common temporal grid. - The Breakpoint times in resampled Partials will comprise a - contiguous sequence of integer multiples of the sampling interval, - beginning with the multiple nearest to the Partial's start time and - ending with the multiple nearest to the Partial's end time. Resampling - is performed in-place. - - */ - -void shapeSpectrum( PartialList * partials, PartialList * surface, - double stretchFreq, double stretchTime ); -/* Scale the amplitudes of a set of Partials by applying - a spectral suface constructed from another set. - Stretch the spectral surface in time and frequency - using the specified stretch factors. Set the stretch - factors to one for no stretching. - */ - -void sift( PartialList * partials ); -/* Identify overlapping Partials having the same (nonzero) - label. If any two partials with same label - overlap in time, set the label of the weaker - (having less total energy) partial to zero. - - */ - -unsigned int -synthesize( const PartialList * partials, - double * buffer, unsigned int bufferSize, - double srate ); -/* Synthesize Partials in a PartialList at the given sample - rate, and store the (floating point) samples in a buffer of - size bufferSize. The buffer is neither resized nor - cleared before synthesis, so newly synthesized samples are - added to any previously computed samples in the buffer, and - samples beyond the end of the buffer are lost. Return the - number of samples synthesized, that is, the index of the - latest sample in the buffer that was modified. - */ - -/* ---------------------------------------------------------------- */ -/* utility functions -/* -/* Operations for transforming and manipulating collections - of Partials. - */ - -double avgAmplitude( const Partial * p ); -/* Return the average amplitude over all Breakpoints in this Partial. - Return zero if the Partial has no Breakpoints. - */ - -double avgFrequency( const Partial * p ); -/* Return the average frequency over all Breakpoints in this Partial. - Return zero if the Partial has no Breakpoints. - */ - -void copyIf( const PartialList * src, PartialList * dst, - int ( * predicate )( const Partial * p, void * data ), - void * data ); -/* Append copies of Partials in the source PartialList satisfying the - specified predicate to the destination PartialList. The source list - is unmodified. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ - -void copyLabeled( const PartialList * src, long label, PartialList * dst ); -/* Append copies of Partials in the source PartialList having the - specified label to the destination PartialList. The source list - is unmodified. - */ - -void crop( PartialList * partials, double t1, double t2 ); -/* Trim Partials by removing Breakpoints outside a specified time span. - Insert a Breakpoint at the boundary when cropping occurs. Remove - any Partials that are left empty after cropping (Partials having no - Breakpoints between t1 and t2). - */ - -void extractIf( PartialList * src, PartialList * dst, - int ( * predicate )( const Partial * p, void * data ), - void * data ); -/* Remove Partials in the source PartialList satisfying the - specified predicate from the source list and append them to - the destination PartialList. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ - -void extractLabeled( PartialList * src, long label, PartialList * dst ); -/* Remove Partials in the source PartialList having the specified - label from the source list and append them to the destination - PartialList. - */ - -void fixPhaseAfter( PartialList * partials, double time ); -/* Recompute phases of all Breakpoints later than the specified - time so that the synthesized phases of those later Breakpoints - matches the stored phase, as long as the synthesized phase at - the specified time matches the stored (not recomputed) phase. - - Phase fixing is only applied to non-null (nonzero-amplitude) - Breakpoints, because null Breakpoints are interpreted as phase - reset points in Loris. If a null is encountered, its phase is - corrected from its non-Null successor, if it has one, otherwise - it is unmodified. - */ - -void fixPhaseAt( PartialList * partials, double time ); -/* Recompute phases of all Breakpoints in a Partial - so that the synthesized phases match the stored phases, - and the synthesized phase at (nearest) the specified - time matches the stored (not recomputed) phase. - - Backward phase-fixing stops if a null (zero-amplitude) - Breakpoint is encountered, because nulls are interpreted as - phase reset points in Loris. If a null is encountered, the - remainder of the Partial (the front part) is fixed in the - forward direction, beginning at the start of the Partial. - Forward phase fixing is only applied to non-null - (nonzero-amplitude) Breakpoints. If a null is encountered, - its phase is corrected from its non-Null successor, if - it has one, otherwise it is unmodified. - */ - -void fixPhaseBefore( PartialList * partials, double time ); -/* Recompute phases of all Breakpoints earlier than the specified - time so that the synthesized phases of those earlier Breakpoints - matches the stored phase, and the synthesized phase at the - specified time matches the stored (not recomputed) phase. - - Backward phase-fixing stops if a null (zero-amplitude) Breakpoint - is encountered, because nulls are interpreted as phase reset - points in Loris. If a null is encountered, the remainder of the - Partial (the front part) is fixed in the forward direction, - beginning at the start of the Partial. - */ - -void fixPhaseBetween( PartialList * partials, double tbeg, double tend ); -/* - Fix the phase travel between two times by adjusting the - frequency and phase of Breakpoints between those two times. - - This algorithm assumes that there is nothing interesting - about the phases of the intervening Breakpoints, and modifies - their frequencies as little as possible to achieve the correct - amount of phase travel such that the frequencies and phases at - the specified times match the stored values. The phases of all - the Breakpoints between the specified times are recomputed. - */ - -void fixPhaseForward( PartialList * partials, double tbeg, double tend ); -/* Recompute phases of all Breakpoints later than the specified - time so that the synthesized phases of those later Breakpoints - matches the stored phase, as long as the synthesized phase at - the specified time matches the stored (not recomputed) phase. - Breakpoints later than tend are unmodified. - - Phase fixing is only applied to non-null (nonzero-amplitude) - Breakpoints, because null Breakpoints are interpreted as phase - reset points in Loris. If a null is encountered, its phase is - corrected from its non-Null successor, if it has one, otherwise - it is unmodified. - */ - -int forEachBreakpoint( Partial * p, - int ( * func )( Breakpoint * p, double time, void * data ), - void * data ); -/* Apply a function to each Breakpoint in a Partial. The function - is called once for each Breakpoint in the source Partial. The - function may modify the Breakpoint (but should not otherwise attempt - to modify the Partial). The data parameter can be used to supply extra - user-defined data to the function. Pass 0 if no additional data is needed. - The function should return 0 if successful. If the function returns - a non-zero value, then forEachBreakpoint immediately returns that value - without applying the function to any other Breakpoints in the Partial. - forEachBreakpoint returns zero if all calls to func return zero. - */ - -int forEachPartial( PartialList * src, - int ( * func )( Partial * p, void * data ), - void * data ); -/* Apply a function to each Partial in a PartialList. The function - is called once for each Partial in the source PartialList. The - function may modify the Partial (but should not attempt to modify - the PartialList). The data parameter can be used to supply extra - user-defined data to the function. Pass 0 if no additional data - is needed. The function should return 0 if successful. If the - function returns a non-zero value, then forEachPartial immediately - returns that value without applying the function to any other - Partials in the PartialList. forEachPartial returns zero if all - calls to func return zero. - */ - -double peakAmplitude( const Partial * p ); -/* Return the maximum amplitude achieved by a Partial. - */ - -void removeIf( PartialList * src, - int ( * predicate )( const Partial * p, void * data ), - void * data ); -/* Remove from a PartialList all Partials satisfying the - specified predicate. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ - -void removeLabeled( PartialList * src, long label ); -/* Remove from a PartialList all Partials having the specified label. - */ - -void scaleAmplitude( PartialList * partials, LinearEnvelope * ampEnv ); -/* Scale the amplitude of the Partials in a PartialList according - to an envelope representing a time-varying amplitude scale value. - */ - -void scaleAmp( PartialList * partials, LinearEnvelope * ampEnv ); -/* Bad old name for scaleAmplitude. - */ - -void scaleBandwidth( PartialList * partials, LinearEnvelope * bwEnv ); -/* Scale the bandwidth of the Partials in a PartialList according - to an envelope representing a time-varying bandwidth scale value. - */ - -void scaleFrequency( PartialList * partials, LinearEnvelope * freqEnv ); -/* Scale the frequency of the Partials in a PartialList according - to an envelope representing a time-varying frequency scale value. - */ - -void scaleNoiseRatio( PartialList * partials, LinearEnvelope * noiseEnv ); -/* Scale the relative noise content of the Partials in a PartialList - according to an envelope representing a (time-varying) noise energy - scale value. - */ - -void setBandwidth( PartialList * partials, LinearEnvelope * bwEnv ); -/* Set the bandwidth of the Partials in a PartialList according - to an envelope representing a time-varying bandwidth value. - */ - -void shiftPitch( PartialList * partials, LinearEnvelope * pitchEnv ); -/* Shift the pitch of all Partials in a PartialList according to - the given pitch envelope. The pitch envelope is assumed to have - units of cents (1/100 of a halfstep). - */ - -void shiftTime( PartialList * partials, double offset ); -/* Shift the time of all the Breakpoints in a Partial by a - constant amount. - */ - -void sortByLabel( PartialList * partials ); -/* Sort the Partials in a PartialList in order of increasing label. - The sort is stable; Partials having the same label are not - reordered. - */ - -void timeSpan( PartialList * partials, double * tmin, double * tmax ); -/* Return the minimum start time and maximum end time - in seconds of all Partials in this PartialList. The v - times are returned in the (non-null) pointers tmin - and tmax. - */ - -double weightedAvgFrequency( const Partial * p ); -/* Return the average frequency over all Breakpoints in this Partial, - weighted by the Breakpoint amplitudes. Return zero if the Partial - has no Breakpoints. - */ - -/* ---------------------------------------------------------------- */ -/* Notification and exception handlers -/* -/* An exception handler and a notifier may be specified. Both - are functions taking a const char * argument and returning - void. - */ - -void setExceptionHandler( void(*f)(const char *) ); -/* Specify a function to call when reporting exceptions. The - function takes a const char * argument, and returns void. - */ - -void setNotifier( void(*f)(const char *) ); -/* Specify a notification function. The function takes a - const char * argument, and returns void. - */ - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -#endif /* ndef INCLUDE_LORIS_H */ diff --git a/loris_library/Source/src/lorisAnalyzer_pi.cpp b/loris_library/Source/src/lorisAnalyzer_pi.cpp deleted file mode 100644 index 192064f..0000000 --- a/loris_library/Source/src/lorisAnalyzer_pi.cpp +++ /dev/null @@ -1,1020 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * lorisAnalyzer_pi.C - * - * A component of the C-linkable procedural interface for Loris. - * - * Main components of the Loris procedural interface: - * - object interfaces - Analyzer, Synthesizer, Partial, PartialIterator, - * PartialList, PartialListIterator, Breakpoint, BreakpointEnvelope, - * and SampleVector need to be (opaque) objects in the interface, - * either because they hold state (e.g. Analyzer) or because they are - * fundamental data types (e.g. Partial), so they need a procedural - * interface to their member functions. All these things need to be - * opaque pointers for the benefit of C. - * - non-object-based procedures - other classes in Loris are not so stateful, - * and have sufficiently narrow functionality that they need only - * procedures, and no object representation. - * - utility functions - some procedures that are generally useful but are - * not yet part of the Loris core are also defined. - * - notification and exception handlers - all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function (the default one in Loris uses printf()). - * - * This file contains the procedural interface for the Loris Analyzer class. - * - * Kelly Fitz, 10 Nov 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "loris.h" -#include "lorisException_pi.h" - -#include "Analyzer.h" -#include "Notifier.h" - -using namespace Loris; - -/* ---------------------------------------------------------------- */ -/* Analyzer object interface -/* -/* An Analyzer represents a configuration of parameters for - performing Reassigned Bandwidth-Enhanced Additive Analysis - of sampled waveforms. This analysis process yields a collection - of Partials, each having a trio of synchronous, non-uniformly- - sampled breakpoint envelopes representing the time-varying - frequency, amplitude, and noisiness of a single bandwidth- - enhanced sinusoid. - - For more information about Reassigned Bandwidth-Enhanced - Analysis and the Reassigned Bandwidth-Enhanced Additive Sound - Model, refer to the Loris website: www.cerlsoundgroup.org/Loris/. - - In the procedural interface, there is only one Analyzer. - It must be configured by calling analyzer_configure before - any of the other analyzer operations can be performed. - */ -static Analyzer * ptr_instance = 0; - -/* ---------------------------------------------------------------- */ -/* analyzer_configure -/* -/* Configure the sole Analyzer instance with the specified - frequency resolution (minimum instantaneous frequency - difference between Partials). All other Analyzer parameters - are computed from the specified frequency resolution. - - Construct the Analyzer instance if necessary. - - In the procedural interface, there is only one Analyzer. - It must be configured by calling analyzer_configure before - any of the other analyzer operations can be performed. - */ -extern "C" -void analyzer_configure( double resolution, double windowWidth, void* tc) -{ - try - { - if ( 0 == ptr_instance ) - { - debugger << "creating Analyzer" << endl; - ptr_instance = new Analyzer( resolution, windowWidth ); - } - else - { - debugger << "configuring Analyzer" << endl; - ptr_instance->configure( resolution, windowWidth ); - } - - if (tc != nullptr) - { - ptr_instance->threadController = static_cast(tc); - } - - } - catch( Exception & ex ) - { - std::string s("Loris exception in createAnalyzer(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in createAnalyzer(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyze -/* -/* Analyze an array of bufferSize (mono) samples at the given - sample rate (in Hz) and append the extracted Partials to the - given PartialList. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyze( const double * buffer, unsigned int bufferSize, - double srate, PartialList * partials ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ThrowIfNull((double *) buffer); - ThrowIfNull((PartialList *) partials); - - // perform analysis: - notifier << "analyzing " << bufferSize << " samples at " << - srate << " Hz with frequency resolution " << - ptr_instance->freqResolution() << endl; - if ( bufferSize > 0 ) - { - ptr_instance->analyze( buffer, buffer + bufferSize, srate ); - - // splice the Partials into the destination list: - partials->splice( partials->end(), ptr_instance->partials() ); - } - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyze(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyze(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_getFreqResolution -/* -/* Return the frequency resolution (minimum instantaneous frequency - difference between Partials) for this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -double analyzer_getFreqResolution( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return 0; - } - - try - { - return ptr_instance->freqResolution(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_getFreqResolution(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_getFreqResolution(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - -/* ---------------------------------------------------------------- */ -/* analyzer_setFreqResolution -/* -/* Set the frequency resolution (minimum instantaneous frequency - difference between Partials) for this Analyzer. (Does not cause - other parameters to be recomputed.) - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_setFreqResolution( double x ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->setFreqResolution( x ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_setFreqResolution(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_setFreqResolution(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_getAmpFloor -/* -/* Return the amplitude floor (lowest detected spectral amplitude), - in (negative) dB, for this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -double analyzer_getAmpFloor( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return 0; - } - - try - { - return ptr_instance->ampFloor(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_getAmpFloor(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_getAmpFloor(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - -/* ---------------------------------------------------------------- */ -/* analyzer_setAmpFloor -/* -/* Set the amplitude floor (lowest detected spectral amplitude), in - (negative) dB, for this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_setAmpFloor( double x ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->setAmpFloor( x ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_setAmpFloor(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_setAmpFloor(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_getWindowWidth -/* -/* Return the frequency-domain main lobe width (measured between - zero-crossings) of the analysis window used by this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -double analyzer_getWindowWidth( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return 0; - } - - try - { - return ptr_instance->windowWidth(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_getWindowWidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_getWindowWidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - -/* ---------------------------------------------------------------- */ -/* analyzer_setWindowWidth -/* -/* Set the frequency-domain main lobe width (measured between - zero-crossings) of the analysis window used by this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_setWindowWidth( double x ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->setWindowWidth( x ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_setWindowWidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_setWindowWidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_getSidelobeLevel -/* -/* Return the sidelobe attenutation level for the Kaiser analysis window in - negative dB. More negative numbers (e.g. -90) give very good sidelobe - rejection but cause the window to be longer in time. Less negative - numbers raise the level of the sidelobes, increasing the liklihood - of frequency-domain interference, but allow the window to be shorter - in time. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -double analyzer_getSidelobeLevel( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return 0; - } - - try - { - return ptr_instance->sidelobeLevel(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_getSidelobeLevel(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_getSidelobeLevel(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - -/* ---------------------------------------------------------------- */ -/* analyzer_setSidelobeLevel -/* -/* Set the sidelobe attenutation level for the Kaiser analysis window in - negative dB. More negative numbers (e.g. -90) give very good sidelobe - rejection but cause the window to be longer in time. Less negative - numbers raise the level of the sidelobes, increasing the liklihood - of frequency-domain interference, but allow the window to be shorter - in time. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_setSidelobeLevel( double x ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->setSidelobeLevel( x ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_setSidelobeLevel(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_setSidelobeLevel(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_getFreqFloor -/* -/* Return the frequency floor (minimum instantaneous Partial - frequency), in Hz, for this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -double analyzer_getFreqFloor( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return 0; - } - - try - { - return ptr_instance->freqFloor(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_getFreqFloor(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_getFreqFloor(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - -/* ---------------------------------------------------------------- */ -/* analyzer_setFreqFloor -/* -/* Set the amplitude floor (minimum instantaneous Partial - frequency), in Hz, for this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_setFreqFloor( double x ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->setFreqFloor( x ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_setFreqFloor(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_setFreqFloor(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_getFreqDrift -/* -/* Return the maximum allowable frequency difference between - consecutive Breakpoints in a Partial envelope for this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -double analyzer_getFreqDrift( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return 0; - } - - try - { - return ptr_instance->freqDrift(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_getFreqDrift(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_getFreqDrift(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - -/* ---------------------------------------------------------------- */ -/* analyzer_setFreqDrift -/* -/* Set the maximum allowable frequency difference between - consecutive Breakpoints in a Partial envelope for this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_setFreqDrift( double x ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->setFreqDrift( x ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_setFreqDrift(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_setFreqDrift(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_getHopTime -/* -/* Return the hop time (which corresponds approximately to the - average density of Partial envelope Breakpoint data) for this - Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -double analyzer_getHopTime( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return 0; - } - - try - { - return ptr_instance->hopTime(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_getHopTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - - { - std::string s("std C++ exception in analyzer_getHopTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - -/* ---------------------------------------------------------------- */ -/* analyzer_setHopTime -/* -/* Set the hop time (which corresponds approximately to the average - density of Partial envelope Breakpoint data) for this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_setHopTime( double x ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->setHopTime( x ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_setHopTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_setHopTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} -/* ---------------------------------------------------------------- */ -/* analyzer_getCropTime -/* -/* Return the crop time (maximum temporal displacement of a time- - frequency data point from the time-domain center of the analysis - window, beyond which data points are considered "unreliable") - for this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -double analyzer_getCropTime( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return 0; - } - - try - { - return ptr_instance->cropTime(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_getCropTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_getCropTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - -/* ---------------------------------------------------------------- */ -/* analyzer_setCropTime -/* -/* Set the crop time (maximum temporal displacement of a time- - frequency data point from the time-domain center of the analysis - window, beyond which data points are considered "unreliable") - for this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_setCropTime( double x ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->setCropTime( x ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_setCropTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_setCropTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_getBwRegionWidth -/* -/* Return the width (in Hz) of the Bandwidth Association regions - used by this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -double analyzer_getBwRegionWidth( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return 0; - } - - try - { - return ptr_instance->bwRegionWidth(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_getBwRegionWidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_getBwRegionWidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - -/* ---------------------------------------------------------------- */ -/* analyzer_setBwRegionWidth -/* -/* Set the width (in Hz) of the Bandwidth Association regions - used by this Analyzer. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_setBwRegionWidth( double x ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->setBwRegionWidth( x ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_setBwRegionWidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_setBwRegionWidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_storeResidueBandwidth -/* -/* Construct Partial bandwidth envelopes during analysis - by associating residual energy in the spectrum (after - peak extraction) with the selected spectral peaks that - are used to construct Partials. - - regionWidth is the width (in Hz) of the bandwidth - association regions used by this process, must be positive. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_storeResidueBandwidth( double regionWidth ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->storeResidueBandwidth( regionWidth ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_storeResidueBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_storeResidueBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_storeConvergenceBandwidth -/* -/* Construct Partial bandwidth envelopes during analysis - by storing the mixed derivative of short-time phase, - scaled and shifted so that a value of 0 corresponds - to a pure sinusoid, and a value of 1 corresponds to a - bandwidth-enhanced sinusoid with maximal energy spread - (minimum sinusoidal convergence). - - tolerance is the amount of range over which the - mixed derivative indicator should be allowed to drift away - from a pure sinusoid before saturating. This range is mapped - to bandwidth values on the range [0,1]. Must be positive and - not greater than 1. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_storeConvergenceBandwidth( double tolerance ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->storeConvergenceBandwidth( tolerance ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_storeConvergenceBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_storeConvergenceBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_storeNoBandwidth -/* -/* Disable bandwidth envelope construction. Bandwidth - will be zero for all Breakpoints in all Partials. - - analyzer_configure must be called before any other analyzer - function. - */ -extern "C" -void analyzer_storeNoBandwidth( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return; - } - - try - { - ptr_instance->storeNoBandwidth(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_storeNoBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_storeNoBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* analyzer_getBwConvergenceTolerance -/* -/* Return the mixed derivative convergence tolerance - only if the convergence indicator is used to compute - bandwidth envelopes. Return zero if the spectral residue - method is used or if no bandwidth is computed. - */ -extern "C" -double analyzer_getBwConvergenceTolerance( void ) -{ - if ( 0 == ptr_instance ) - { - handleException( "analyzer_configure must be called before any other analyzer function." ); - return 0; - } - - try - { - return ptr_instance->bwConvergenceTolerance(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in analyzer_getBwConvergenceTolerance(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in analyzer_getBwConvergenceTolerance(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - - return 0; -} - - - - - diff --git a/loris_library/Source/src/lorisBpEnvelope_pi.cpp b/loris_library/Source/src/lorisBpEnvelope_pi.cpp deleted file mode 100644 index 8015006..0000000 --- a/loris_library/Source/src/lorisBpEnvelope_pi.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * lorisBpEnvelope_pi.C - * - * A component of the C-linkable procedural interface for Loris. - * - * Main components of this interface: - * - version identification symbols - * - type declarations - * - Analyzer configuration - * - LinearEnvelope (formerly BreakpointEnvelope) operations - * - PartialList operations - * - Partial operations - * - Breakpoint operations - * - sound modeling functions for preparing PartialLists - * - utility functions for manipulating PartialLists - * - notification and exception handlers (all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function. The default one in Loris uses printf()). - * - * This file defines the procedural interface for the Loris - * BreakpointEnvelope class. - * - * Kelly Fitz, 10 Nov 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "loris.h" -#include "lorisException_pi.h" - -#include "LinearEnvelope.h" -#include "Notifier.h" - -using namespace Loris; - -/* ---------------------------------------------------------------- */ -/* LinearEnvelope object interface -/* -/* A LinearEnvelope represents a linear segment breakpoint - function with infinite extension at each end (that is, the - values past either end of the breakpoint function have the - values at the nearest end). - */ - -/* ---------------------------------------------------------------- */ -/* createLinearEnvelope -/* -/* Construct and return a new LinearEnvelope having no - breakpoints and an implicit value of 0. everywhere, - until the first breakpoint is inserted. - */ -extern "C" -LinearEnvelope * createLinearEnvelope( void ) -{ - try - { - debugger << "creating LinearEnvelope" << endl; - return new LinearEnvelope(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in createLinearEnvelope(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in createLinearEnvelope(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return NULL; -} - -/* ---------------------------------------------------------------- */ -/* copyLinearEnvelope -/* -/* Construct and return a new LinearEnvelope that is an - exact copy of the specified LinearEnvelopes, having - an identical set of breakpoints. - */ -extern "C" -LinearEnvelope * copyLinearEnvelope( const LinearEnvelope * ptr_this ) -{ - try - { - debugger << "copying LinearEnvelope" << endl; - return new LinearEnvelope( *ptr_this ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in copyLinearEnvelope(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in copyLinearEnvelope(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return NULL; -} - -/* ---------------------------------------------------------------- */ -/* destroyLinearEnvelope -/* -/* Destroy this LinearEnvelope. - */ -extern "C" -void destroyLinearEnvelope( LinearEnvelope * ptr_this ) -{ - try - { - ThrowIfNull((LinearEnvelope *) ptr_this); - - debugger << "deleting LinearEnvelope" << endl; - delete ptr_this; - } - catch( Exception & ex ) - { - std::string s("Loris exception in destroyLinearEnvelope(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in destroyLinearEnvelope(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* linearEnvelope_insertBreakpoint -/* -/* Insert a breakpoint representing the specified (time, value) - pair into this LinearEnvelope. If there is already a - breakpoint at the specified time, it will be replaced with - the new breakpoint. - */ -extern "C" -void linearEnvelope_insertBreakpoint( LinearEnvelope * ptr_this, - double time, double val ) -{ - try - { - ThrowIfNull((LinearEnvelope *) ptr_this); - - debugger << "inserting point (" << time << ", " << val - << ") into LinearEnvelope" << endl; - ptr_this->insertBreakpoint(time, val); - } - catch( Exception & ex ) - { - std::string s("Loris exception in linearEnvelope_insertBreakpoint(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in linearEnvelope_insertBreakpoint(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* linearEnvelope_valueAt -/* -/* Return the interpolated value of this LinearEnvelope at the - specified time. - */ -extern "C" -double linearEnvelope_valueAt( const LinearEnvelope * ptr_this, - double time ) -{ - try - { - ThrowIfNull((LinearEnvelope *) ptr_this); - return ptr_this->valueAt(time); - } - catch( Exception & ex ) - { - std::string s("Loris exception in linearEnvelope_valueAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in linearEnvelope_valueAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - diff --git a/loris_library/Source/src/lorisException_pi.cpp b/loris_library/Source/src/lorisException_pi.cpp deleted file mode 100644 index 86a6398..0000000 --- a/loris_library/Source/src/lorisException_pi.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * lorisException_pi.C - * - * A component of the C-linkable procedural interface for Loris. - * - * Main components of the Loris procedural interface: - * - object interfaces - Analyzer, Synthesizer, Partial, PartialIterator, - * PartialList, PartialListIterator, Breakpoint, BreakpointEnvelope, - * and SampleVector need to be (opaque) objects in the interface, - * either because they hold state (e.g. Analyzer) or because they are - * fundamental data types (e.g. Partial), so they need a procedural - * interface to their member functions. All these things need to be - * opaque pointers for the benefit of C. - * - non-object-based procedures - other classes in Loris are not so stateful, - * and have sufficiently narrow functionality that they need only - * procedures, and no object representation. - * - utility functions - some procedures that are generally useful but are - * not yet part of the Loris core are also defined. - * - notification and exception handlers - all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function (the default one in Loris uses printf()). - * - * This file defines the exception and notification handling functions - * used in the Loris procedural interface. - * - * Kelly Fitz, 10 Nov 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "lorisException_pi.h" - - -#include "loris.h" -#include "Notifier.h" - -using namespace Loris; - -/* ---------------------------------------------------------------- */ -/* notification and exception handlers -/* -/* - An exception handler and a notifier may be specified. Both - are functions taking a const char * argument and returning - void. - */ - -/* ---------------------------------------------------------------- */ -/* handleException -/* -/* Report exceptions thrown out of Loris. If no handler is - specified, report them using Loris' notifier and return - without further incident. - */ -static void(*ex_handler)(const char *) = NULL; -void handleException( const char * s ) -{ - if ( ex_handler ) - ex_handler( s ); - else - notifier << s << endl; -} - -/* ---------------------------------------------------------------- */ -/* setExceptionHandler -/* -/* Specify a function to call when reporting exceptions. The - function takes a const char * argument, and returns void. - */ -extern "C" -void setExceptionHandler( void(*f)(const char *) ) -{ - ex_handler = f; -} - -/* ---------------------------------------------------------------- */ -/* setNotifier -/* */ -/* Specify a notification function. The function takes a - const char * argument, and returns void. - */ -extern "C" -void setNotifier( void(*f)(const char *) ) -{ - // these are guaranteed not to throw: - setNotifierHandler( f ); - setDebuggerHandler( f ); -} - diff --git a/loris_library/Source/src/lorisException_pi.h b/loris_library/Source/src/lorisException_pi.h deleted file mode 100644 index 8dddc2a..0000000 --- a/loris_library/Source/src/lorisException_pi.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef INCLUDE_LORISEXCEPTION_PI_H -#define INCLUDE_LORISEXCEPTION_PI_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * lorisException_pi.h - * - * A component of the C-linkable procedural interface for Loris. - * - * Main components of the Loris procedural interface: - * - object interfaces - Analyzer, Synthesizer, Partial, PartialIterator, - * PartialList, PartialListIterator, Breakpoint, BreakpointEnvelope, - * and SampleVector need to be (opaque) objects in the interface, - * either because they hold state (e.g. Analyzer) or because they are - * fundamental data types (e.g. Partial), so they need a procedural - * interface to their member functions. All these things need to be - * opaque pointers for the benefit of C. - * - non-object-based procedures - other classes in Loris are not so stateful, - * and have sufficiently narrow functionality that they need only - * procedures, and no object representation. - * - utility functions - some procedures that are generally useful but are - * not yet part of the Loris core are also defined. - * - notification and exception handlers - all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function (the default one in Loris uses printf()). - * - * This file declares the exception handling functions used in the - * Loris procedural interface. - * - * Kelly Fitz, 10 Nov 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ - -#include "LorisExceptions.h" -#include - -// forward-declare local exception handler: -void handleException( const char * s ); - -/* ---------------------------------------------------------------- */ -/* class NullPointer -/* -/* Exception subclass for catching NULL pointers: - */ -class NullPointer : public Loris::Exception -{ -public: - NullPointer( const std::string & str, const std::string & where = "" ) : - Exception( std::string("NULL pointer exception -- ").append( str ), where ) {} -}; // end of class NullPointer - -#define ThrowIfNull(ptr) if ((ptr)==NULL) Throw( NullPointer, #ptr ); - - -#endif /* ndef INCLUDE_LORISEXCEPTION_PI_H */ diff --git a/loris_library/Source/src/lorisNonObj_pi.cpp b/loris_library/Source/src/lorisNonObj_pi.cpp deleted file mode 100644 index 0a9f55d..0000000 --- a/loris_library/Source/src/lorisNonObj_pi.cpp +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * lorisNonObj_pi.C - * - * A component of the C-linkable procedural interface for Loris. - * - * Main components of this interface: - * - version identification symbols - * - type declarations - * - Analyzer configuration - * - LinearEnvelope (formerly BreakpointEnvelope) operations - * - PartialList operations - * - Partial operations - * - Breakpoint operations - * - sound modeling functions for preparing PartialLists - * - utility functions for manipulating PartialLists - * - notification and exception handlers (all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function. The default one in Loris uses printf()). - * - * This file defines the non-object-based component of the Loris - * procedural interface. - * - * Kelly Fitz, 10 Nov 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "loris.h" -#include "lorisException_pi.h" - -#include "AiffFile.h" -#include "Analyzer.h" -#include "BreakpointEnvelope.h" -#include "Channelizer.h" -#include "Collator.h" -#include "Dilator.h" -#include "Distiller.h" -#include "LorisExceptions.h" -#include "FrequencyReference.h" -#include "Fundamental.h" -#include "Harmonifier.h" -#include "ImportLemur.h" -#include "Morpher.h" -#include "Notifier.h" -#include "Partial.h" -#include "PartialUtils.h" -#include "Resampler.h" -#include "SdifFile.h" -#include "Sieve.h" -#include "SpcFile.h" -#include "SpectralSurface.h" -#include "Synthesizer.h" - -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace Loris; - -/* ---------------------------------------------------------------- */ -/* non-object-based procedures -/* -/* Operations in Loris that need not be accessed though object - interfaces are represented as simple functions. - */ - -/* ---------------------------------------------------------------- */ -/* channelize -/* -/* Label Partials in a PartialList with the integer nearest to - the amplitude-weighted average ratio of their frequency envelope - to a reference frequency envelope. The frequency spectrum is - partitioned into non-overlapping channels whose time-varying - center frequencies track the reference frequency envelope. - The reference label indicates which channel's center frequency - is exactly equal to the reference envelope frequency, and other - channels' center frequencies are multiples of the reference - envelope frequency divided by the reference label. Each Partial - in the PartialList is labeled with the number of the channel - that best fits its frequency envelope. The quality of the fit - is evaluated at the breakpoints in the Partial envelope and - weighted by the amplitude at each breakpoint, so that high- - amplitude breakpoints contribute more to the channel decision. - Partials are labeled, but otherwise unmodified. In particular, - their frequencies are not modified in any way. - */ -extern "C" -void channelize( PartialList * partials, - LinearEnvelope * refFreqEnvelope, int refLabel ) -{ - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((LinearEnvelope *) refFreqEnvelope); - - if ( refLabel <= 0 ) - { - Throw( InvalidArgument, "Channelization reference label must be positive." ); - } - notifier << "channelizing " << partials->size() << " Partials" << endl; - - Channelizer::channelize( *partials, *refFreqEnvelope, refLabel ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in channelize(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in channelize(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* collate -/* -/* Collate unlabeled (zero-labeled) Partials into the smallest-possible - number of Partials that does not combine any overlapping Partials. - Collated Partials assigned labels higher than any label in the original - list, and appear at the end of the sequence, after all previously-labeled - Partials. - */ -extern "C" -void collate( PartialList * partials ) -{ - try - { - ThrowIfNull((PartialList *) partials); - - notifier << "collating " << partials->size() << " Partials" << endl; - - // Uses default fade time of 1 ms, and .1 ms gap, - // should be parameters. - Collator::collate( *partials, 0.001, 0.0001 ); - - } - catch( Exception & ex ) - { - std::string s("Loris exception in collate(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in collate(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* createFreqReference -/* -/* Return a newly-constructed LinearEnvelope using the legacy - FrequencyReference class. The envelope will have approximately - the specified number of samples. The specified number of samples - must be greater than 1. Uses the FundamentalEstimator - (FundamentalFromPartials) class to construct an estimator of - fundamental frequency, configured to emulate the behavior of - the FrequencyReference class in Loris 1.4-1.5.2. If numSamps - is zero, construct the reference envelope from fundamental - estimates taken every five milliseconds. - - - For simple sounds, this frequency reference may be a - good first approximation to a reference envelope for - channelization (see channelize()). - - Clients are responsible for disposing of the newly-constructed - LinearEnvelope. - */ -extern "C" -LinearEnvelope * -createFreqReference( PartialList * partials, double minFreq, double maxFreq, - long numSamps ) -{ - try - { - ThrowIfNull((PartialList *) partials); - - // use auto_ptr to manage memory in case - // an exception is generated (hard to imagine): - std::auto_ptr< LinearEnvelope > env_ptr; - if ( numSamps != 0 ) - { - env_ptr.reset( new LinearEnvelope( - FrequencyReference( partials->begin(), partials->end(), - minFreq, maxFreq, numSamps ).envelope() ) ); - } - else - { - env_ptr.reset( new LinearEnvelope( - FrequencyReference( partials->begin(), partials->end(), - minFreq, maxFreq ).envelope() ) ); - } - - return env_ptr.release(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in createFreqReference(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in createFreqReference(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return NULL; -} - -/* ---------------------------------------------------------------- */ -/* createF0Estimate -/* -/* Return a newly-constructed LinearEnvelope that estimates - the time-varying fundamental frequency of the sound - represented by the Partials in a PartialList. This uses - the FundamentalEstimator (FundamentalFromPartials) - class to construct an estimator of fundamental frequency, - and returns a LinearEnvelope that samples the estimator at the - specified time interval (in seconds). Default values are used - to configure the estimator. Only estimates in the specified - frequency range will be considered valid, estimates outside this - range will be ignored. - - Clients are responsible for disposing of the newly-constructed - LinearEnvelope. - */ -extern "C" -LinearEnvelope * -createF0Estimate( PartialList * partials, double minFreq, double maxFreq, - double interval, void* threadController) -{ - try - { - ThrowIfNull((PartialList *) partials); - - const double Precision = 0.1; - const double Confidence = 0.9; - FundamentalFromPartials est( Precision ); - est.controller = static_cast(threadController); - - std::pair< double, double > span = - PartialUtils::timeSpan( partials->begin(), partials->end() ); - - LinearEnvelope * env_ptr = - new LinearEnvelope( est.buildEnvelope( partials->begin(), - partials->end(), - span.first, span.second, interval, - minFreq, maxFreq, - Confidence ) ); - return env_ptr; - } - catch( Exception & ex ) - { - std::string s("Loris exception in createF0Estimate(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in createF0Estimate(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return NULL; -} - -/* ---------------------------------------------------------------- */ -/* dilate -/* -/* Dilate Partials in a PartialList according to the given - initial and target time points. Partial envelopes are - stretched and compressed so that temporal features at - the initial time points are aligned with the final time - points. Time points are sorted, so Partial envelopes are - are only stretched and compressed, but breakpoints are not - reordered. Duplicate time points are allowed. There must be - the same number of initial and target time points. - */ -extern "C" -void dilate( PartialList * partials, - const double * initial, const double * target, int npts ) -{ - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((double *) initial); - ThrowIfNull((double *) target); - - notifier << "dilating " << partials->size() << " Partials" << endl; - Dilator::dilate( partials->begin(), partials->end(), - initial, initial + npts, target ); - - } - catch( Exception & ex ) - { - std::string s("Loris exception in dilate(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in dilate(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* distill -/* -/* Distill labeled (channelized) Partials in a PartialList into a - PartialList containing at most one Partial per label. Unlabeled - (zero-labeled) Partials are left unmodified at the end of the - distilled Partials. - */ -extern "C" -void distill( PartialList * partials ) -{ - try - { - ThrowIfNull((PartialList *) partials); - - notifier << "distilling " << partials->size() << " Partials" << endl; - - // uses default fade time of 1 ms, should be parameter - Distiller::distill( *partials, 0.001 ); - - } - catch( Exception & ex ) - { - std::string s("Loris exception in distill(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in distill(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* exportAiff -/* -/* Export mono audio samples stored in an array of size bufferSize to - an AIFF file having the specified sample rate at the given file path - (or name). The floating point samples in the buffer are clamped to the - range (-1.,1.) and converted to integers having bitsPerSamp bits. - */ -extern "C" -void exportAiff( const char * path, const double * buffer, - unsigned int bufferSize, double samplerate, int bitsPerSamp ) -{ - try - { - ThrowIfNull((double *) buffer); - - // do nothing if there are no samples: - if ( bufferSize == 0 ) - { - notifier << "no samples to write to " << path << endl; - return; - } - - // write out samples: - notifier << "writing " << bufferSize << " samples to " << path << endl; - AiffFile fout( buffer, bufferSize, samplerate ); - fout.write( path, bitsPerSamp ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in exportAiff(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in exportAiff(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - -} - -/* ---------------------------------------------------------------- */ -/* exportSdif -/* -/* Export Partials in a PartialList to a SDIF file at the specified - file path (or name). SDIF data is written in the 1TRC format. - For more information about SDIF, see the SDIF web site at: - www.ircam.fr/equipes/analyse-synthese/sdif/ - */ -extern "C" -void exportSdif( const char * path, PartialList * partials ) -{ - try - { - ThrowIfNull((PartialList *) partials); - - if ( partials->size() == 0 ) - { - Throw( Loris::InvalidObject, "No Partials in PartialList to export to sdif file." ); - } - - notifier << "exporting sdif partial data to " << path << endl; - - SdifFile fout( partials->begin(), partials->end() ); - fout.write( path ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in exportSdif(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in exportSdif(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - -} - -/* ---------------------------------------------------------------- */ -/* exportSpc -/* -/* Export Partials in a PartialList to a Spc file at the specified file - path (or name). The fractional MIDI pitch must be specified. The - enhanced parameter defaults to true (for bandwidth-enhanced spc files), - but an be specified false for pure-sines spc files. The endApproachTime - parameter is in seconds. A nonzero endApproachTime indicates that the plist does - not include a release, but rather ends in a static spectrum corresponding - to the final breakpoint values of the partials. The endApproachTime - specifies how long before the end of the sound the amplitude, frequency, - and bandwidth values are to be modified to make a gradual transition to - the static spectrum. - */ -extern "C" -void exportSpc( const char * path, PartialList * partials, double midiPitch, - int enhanced, double endApproachTime ) -{ - try - { - ThrowIfNull((PartialList *) partials); - - if ( partials->size() == 0 ) - { - Throw( InvalidObject, "No Partials in PartialList to export to Spc file." ); - } - - notifier << "exporting Spc partial data to " << path << endl; - - SpcFile fout( midiPitch ); - PartialList::size_type countPartials = 0; - for ( PartialList::iterator iter = partials->begin(); iter != partials->end(); ++iter ) - { - if ( iter->label() > 0 && iter->label() < 512 ) - // should have a symbol defined for 512!!! - { - fout.addPartial( *iter ); - ++countPartials; - } - } - - if ( countPartials != partials->size() ) - { - notifier << "exporting " << countPartials << " of " - << partials->size() << " Partials having labels less than 512." << endl; - } - if ( countPartials == 0 ) - { - Throw( InvalidObject, "No Partials in PartialList have valid Spc labels (1-511)." ); - } - - if ( 0 == enhanced ) - { - fout.writeSinusoidal( path, endApproachTime ); - } - else - { - fout.write( path, endApproachTime ); - } - } - catch( Exception & ex ) - { - std::string s("Loris exception in exportSpc(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in exportSdif(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - -} - -/* ---------------------------------------------------------------- */ -/* harmonify -/* -/* Apply a reference Partial to fix the frequencies of Breakpoints - whose amplitude is below threshold_dB. 0 harmonifies full-amplitude - Partials, to apply only to quiet Partials, specify a lower - threshold like -90). The reference Partial is the first Partial - in the PartialList labeled refLabel (usually 1). The Envelope - is a time-varying weighting on the harmonifing process. When 1, - harmonic frequencies are used, when 0, breakpoint frequencies are - unmodified. - */ -extern "C" -void harmonify( PartialList * partials, long refLabel, - const LinearEnvelope * env, double threshold_dB ) -{ - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((LinearEnvelope *) env); - - if ( partials->size() == 0 ) - { - Throw( InvalidObject, "No Partials in PartialList to harmonify." ); - } - - notifier << "harmonifying " << partials->size() << " Partials" << endl; - - Harmonifier::harmonify( partials->begin(), partials->end(), refLabel, - *env, threshold_dB ); - - } - catch( Exception & ex ) - { - std::string s("Loris exception in harmonify(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in harmonify(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - -} - -/* ---------------------------------------------------------------- */ -/* importAiff -/* -/* Import audio samples stored in an AIFF file at the given file - path (or name). The samples are converted to floating point - values on the range (-1.,1.) and stored in an array of doubles. - The value returned is the number of samples in buffer, and it is at - most bufferSize. If samplerate is not a NULL pointer, - then, on return, it points to the value of the sample rate (in - Hz) of the AIFF samples. The AIFF file must contain only a single - channel of audio data. The prior contents of buffer, if any, are - overwritten. - */ -extern "C" -unsigned int -importAiff( const char * path, double * buffer, unsigned int bufferSize, - double * samplerate ) -{ - unsigned int howMany = 0; - try - { - // read samples: - notifier << "reading samples from " << path << endl; - AiffFile f( path ); - notifier << "read " << f.samples().size() << " frames at " - << f.sampleRate() << " Hz" << endl; - - howMany = std::min( f.samples().size(), - std::vector< double >::size_type( bufferSize ) ); - if ( howMany < f.samples().size() ) - { - notifier << "returning " << howMany << " samples" << endl; - } - - std::copy( f.samples().begin(), f.samples().begin() + howMany, - buffer ); - std::fill( buffer + howMany, buffer + bufferSize, 0. ); - - - if ( samplerate ) - { - *samplerate = f.sampleRate(); - } - } - catch( Exception & ex ) - { - std::string s("Loris exception in importAiff(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in importAiff(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return howMany; -} - -/* ---------------------------------------------------------------- */ -/* importSdif -/* -/* Import Partials from an SDIF file at the given file path (or - name), and append them to a PartialList. Loris reads SDIF - files in the 1TRC format. For more information about SDIF, - see the SDIF web site at: - www.ircam.fr/equipes/analyse-synthese/sdif/ - */ -extern "C" -void importSdif( const char * path, PartialList * partials ) -{ - try - { - ThrowIfNull((PartialList *) partials); - - notifier << "importing Partials from " << path << endl; - SdifFile imp( path ); - partials->splice( partials->end(), imp.partials() ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in importSdif(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in importSdif(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* importSpc -/* -/* Import Partials from an Spc file at the given file path (or - name), and return them in a PartialList. - */ -extern "C" -void importSpc( const char * path, PartialList * partials ) -{ - try - { - Loris::notifier << "importing Partials from " << path << Loris::endl; - Loris::SpcFile imp( path ); - partials->insert( partials->end(), imp.partials().begin(), imp.partials().end() ); - - } - catch( Exception & ex ) - { - std::string s("Loris exception in importSpc(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in importSpc(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* morpher_setAmplitudeShape -/* -/* Set the shaping parameter for the amplitude morphing - function. This shaping parameter controls the - slope of the amplitude morphing function, - for values greater than 1, this function - gets nearly linear (like the old amplitude - morphing function), for values much less - than 1 (e.g. 1E-5) the slope is gently - curved and sounds pretty "linear", for - very small values (e.g. 1E-12) the curve - is very steep and sounds un-natural because - of the huge jump from zero amplitude to - very small amplitude. - - Use LORIS_DEFAULT_AMPMORPHSHAPE to obtain the - default amplitude morphing shape for Loris, - (equal to 1E-5, which works well for many musical - instrument morphs, unless Loris was compiled - with the symbol LINEAR_AMP_MORPHS defined, in - which case LORIS_DEFAULT_AMPMORPHSHAPE is equal - to LORIS_LINEAR_AMPMORPHSHAPE). - - Use LORIS_LINEAR_AMPMORPHSHAPE to approximate - the linear amplitude morphs performed by older - versions of Loris. - - The amplitude shape must be positive. - */ -#if !defined(LINEAR_AMP_MORPHS) || !LINEAR_AMP_MORPHS - const double LORIS_DEFAULT_AMPMORPHSHAPE = 1E-5; -#else - const double LORIS_DEFAULT_AMPMORPHSHAPE = 1E5; -#endif - -const double LORIS_LINEAR_AMPMORPHSHAPE = 1E5; - -static double PI_ampMorphShape = LORIS_DEFAULT_AMPMORPHSHAPE; -extern "C" -void morpher_setAmplitudeShape( double x ) -{ - if ( x <= 0. ) - { - std::string s("Loris exception in morpher_setAmplitudeShape(): " ); - s.append( "Invalid Argument: the amplitude morph shaping parameter must be positive" ); - handleException( s.c_str() ); - } - PI_ampMorphShape = x; -} - -/* ---------------------------------------------------------------- */ -/* morph -/* -/* Morph labeled Partials in two PartialLists according to the - given frequency, amplitude, and bandwidth (noisiness) morphing - envelopes, and append the morphed Partials to the destination - PartialList. Loris morphs Partials by interpolating frequency, - amplitude, and bandwidth envelopes of corresponding Partials in - the source PartialLists. For more information about the Loris - morphing algorithm, see the Loris website: - www.cerlsoundgroup.org/Loris/ - */ -extern "C" -void morph( const PartialList * src0, const PartialList * src1, - const LinearEnvelope * ffreq, - const LinearEnvelope * famp, - const LinearEnvelope * fbw, - PartialList * dst ) -{ - try - { - ThrowIfNull((PartialList *) src0); - ThrowIfNull((PartialList *) src1); - ThrowIfNull((PartialList *) dst); - ThrowIfNull((LinearEnvelope *) ffreq); - ThrowIfNull((LinearEnvelope *) famp); - ThrowIfNull((LinearEnvelope *) fbw); - - notifier << "morphing " << src0->size() << " Partials with " << - src1->size() << " Partials" << endl; - - // make a Morpher object and do it: - Morpher m( *ffreq, *famp, *fbw ); - m.morph( src0->begin(), src0->end(), src1->begin(), src1->end() ); - - // splice the morphed Partials into dst: - dst->splice( dst->end(), m.partials() ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in morph(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in morph(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* morphWithReference -/* -/* Morph labeled Partials in two PartialLists according to the - given frequency, amplitude, and bandwidth (noisiness) morphing - envelopes, and append the morphed Partials to the destination - PartialList. Specify the labels of the Partials to be used as - reference Partial for the two morph sources. The reference - partial is used to compute frequencies for very low-amplitude - Partials whose frequency estimates are not considered reliable. - The reference Partial is considered to have good frequency - estimates throughout. A reference label of 0 indicates that - no reference Partial should be used for the corresponding - morph source. - - Loris morphs Partials by interpolating frequency, - amplitude, and bandwidth envelopes of corresponding Partials in - the source PartialLists. For more information about the Loris - morphing algorithm, see the Loris website: - www.cerlsoundgroup.org/Loris/ - */ -extern "C" -void morphWithReference( const PartialList * src0, - const PartialList * src1, - long src0RefLabel, - long src1RefLabel, - const LinearEnvelope * ffreq, - const LinearEnvelope * famp, - const LinearEnvelope * fbw, - PartialList * dst ) -{ - try - { - ThrowIfNull((PartialList *) src0); - ThrowIfNull((PartialList *) src1); - ThrowIfNull((PartialList *) dst); - ThrowIfNull((LinearEnvelope *) ffreq); - ThrowIfNull((LinearEnvelope *) famp); - ThrowIfNull((LinearEnvelope *) fbw); - - notifier << "morphing " << src0->size() << " Partials with " - << src1->size() << " Partials" << endl; - - // make a Morpher object and do it: - Morpher m( *ffreq, *famp, *fbw ); - - if ( src0RefLabel != 0 ) - { - notifier << "using Partial labeled " << src0RefLabel; - notifier << " as reference Partial for first morph source" << endl; - m.setSourceReferencePartial( *src0, src0RefLabel ); - } - else - { - notifier << "using no reference Partial for first morph source" << endl; - } - - if ( src1RefLabel != 0 ) - { - notifier << "using Partial labeled " << src1RefLabel; - notifier << " as reference Partial for second morph source" << endl; - m.setTargetReferencePartial( *src1, src1RefLabel ); - } - else - { - notifier << "using no reference Partial for second morph source" << endl; - } - - m.morph( src0->begin(), src0->end(), src1->begin(), src1->end() ); - - // splice the morphed Partials into dst: - dst->splice( dst->end(), m.partials() ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in morphWithReference(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in morphWithReference(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - - -/* ---------------------------------------------------------------- */ -/* resample -/* -/* Resample all Partials in a PartialList using the specified - sampling interval, so that the Breakpoints in the Partial - envelopes will all lie on a common temporal grid. - The Breakpoint times in resampled Partials will comprise a - contiguous sequence of integer multiples of the sampling interval, - beginning with the multiple nearest to the Partial's start time and - ending with the multiple nearest to the Partial's end time. Resampling - is performed in-place. - - */ -extern "C" -void resample( PartialList * partials, double interval ) -{ - try - { - ThrowIfNull((PartialList *) partials); - - notifier << "resampling " << partials->size() << " Partials" << Loris::endl; - - Resampler::resample( partials->begin(), partials->end(), interval ); - - // remove any resulting empty Partials - PartialList::iterator it = partials->begin(); - while ( it != partials->end() ) - { - if ( 0 == it->numBreakpoints() ) - { - it = partials->erase( it ); - } - else - { - ++it; - } - } - - } - catch( Exception & ex ) - { - std::string s( "Loris exception in resample(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s( "std C++ exception in resample(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* shapeSpectrum -/* Scale the amplitudes of a set of Partials by applying - a spectral suface constructed from another set. - Strecth the spectral surface in time and frequency - using the specified stretch factors. - */ -extern "C" -void shapeSpectrum( PartialList * partials, PartialList * surface, - double stretchFreq, double stretchTime ) -{ - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((PartialList *) surface); - - notifier << "shaping " << partials->size() << " Partials using " - << "spectral surface created from " << surface->size() - << " Partials" << Loris::endl; - - // uses default fade time of 1 ms, should be parameter - SpectralSurface surf( surface->begin(), surface->end() ); - surf.setFrequencyStretch( stretchFreq ); - surf.setTimeStretch( stretchTime ); - surf.setEffect( 1.0 ); // should this be a parameter? - surf.scaleAmplitudes( partials->begin(), partials->end() ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in shapeSpectrum(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in shapeSpectrum(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} -/* ---------------------------------------------------------------- */ -/* sift -/* Eliminate overlapping Partials having the same label - (except zero). If any two partials with same label - overlap in time, keep only the longer of the two. - Set the label of the shorter duration partial to zero. - - */ -extern "C" -void sift( PartialList * partials ) -{ - try - { - ThrowIfNull((PartialList *) partials); - - notifier << "sifting " << partials->size() << " Partials" << Loris::endl; - - // uses default fade time of 1 ms, should be parameter - Sieve::sift( partials->begin(), partials->end(), 0.001 ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in sift(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in sift(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* synthesize -/* -/* Synthesize Partials in a PartialList at the given sample - rate, and store the (floating point) samples in a buffer of - size bufferSize. The buffer is neither resized nor - cleared before synthesis, so newly synthesized samples are - added to any previously computed samples in the buffer, and - samples beyond the end of the buffer are lost. Return the - number of samples synthesized, that is, the index of the - latest sample in the buffer that was modified. - */ -extern "C" -unsigned int synthesize( const PartialList * partials, - double * buffer, unsigned int bufferSize, - double srate ) -{ - unsigned int howMany = 0; - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((double *) buffer); - - notifier << "synthesizing " << partials->size() - << " Partials at " << srate << " Hz" << endl; - - // synthesize: - std::vector< double > vec; - Synthesizer synth( srate, vec ); - synth.synthesize( partials->begin(), partials->end() ); - - // determine the number of synthesized samples - // that will be stored: - howMany = vec.size(); - if ( howMany > bufferSize ) - { - howMany = bufferSize; - } - - // accumulate into the buffer: - std::transform( buffer, buffer + howMany, vec.begin(), - buffer, std::plus< double >() ); - - - } - catch( Exception & ex ) - { - std::string s("Loris exception in synthesize(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in synthesize(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return howMany; -} - - - - diff --git a/loris_library/Source/src/lorisPartialList_pi.cpp b/loris_library/Source/src/lorisPartialList_pi.cpp deleted file mode 100644 index c99c77c..0000000 --- a/loris_library/Source/src/lorisPartialList_pi.cpp +++ /dev/null @@ -1,839 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * lorisPartialList_pi.C - * - * A component of the C-linkable procedural interface for Loris. - * - * Main components of the Loris procedural interface: - * - object interfaces - Analyzer, Synthesizer, Partial, PartialIterator, - * PartialList, PartialListIterator, Breakpoint, BreakpointEnvelope, - * and SampleVector need to be (opaque) objects in the interface, - * either because they hold state (e.g. Analyzer) or because they are - * fundamental data types (e.g. Partial), so they need a procedural - * interface to their member functions. All these things need to be - * opaque pointers for the benefit of C. - * - non-object-based procedures - other classes in Loris are not so stateful, - * and have sufficiently narrow functionality that they need only - * procedures, and no object representation. - * - utility functions - some procedures that are generally useful but are - * not yet part of the Loris core are also defined. - * - notification and exception handlers - all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function (the default one in Loris uses printf()). - * - * This file contains the procedural interface for the Loris - * PartialList (std::list< Partial >) class. - * - * Kelly Fitz, 10 Nov 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "loris.h" -#include "lorisException_pi.h" - -#include "Partial.h" -#include "Notifier.h" - -#include - -using namespace Loris; - - -/* ---------------------------------------------------------------- */ -/* PartialList object interface -/* -/* A PartialList represents a collection of Bandwidth-Enhanced - Partials, each having a trio of synchronous, non-uniformly- - sampled breakpoint envelopes representing the time-varying - frequency, amplitude, and noisiness of a single bandwidth- - enhanced sinusoid. - - For more information about Bandwidth-Enhanced Partials and the - Reassigned Bandwidth-Enhanced Additive Sound Model, refer to - the Loris website: www.cerlsoundgroup.org/Loris/. - - In C++, a PartialList * is a Loris::PartialList *. - */ - -/* ---------------------------------------------------------------- */ -/* createPartialList -/* -/* Return a new empty PartialList. - */ -extern "C" -PartialList * createPartialList( void ) -{ - try - { - debugger << "creating empty PartialList" << endl; - return new std::list< Partial >; - } - catch( Exception & ex ) - { - std::string s("Loris exception in createPartialList(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in createPartialList(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return NULL; -} - -/* ---------------------------------------------------------------- */ -/* destroyPartialList -/* -/* Destroy this PartialList. - */ -extern "C" -void destroyPartialList( PartialList * ptr_this ) -{ - try - { - ThrowIfNull((PartialList *) ptr_this); - - debugger << "deleting PartialList containing " << ptr_this->size() << " Partials" << endl; - delete ptr_this; - } - catch( Exception & ex ) - { - std::string s("Loris exception in destroyPartialList(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in destroyPartialList(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* partialList_clear -/* -/* Remove (and destroy) all the Partials from this PartialList, - leaving it empty. - */ -extern "C" -void partialList_clear( PartialList * ptr_this ) -{ - try - { - ThrowIfNull((PartialList *) ptr_this); - ptr_this->clear(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partialList_clear(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partialList_clear(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* partialList_copy -/* -/* Make this PartialList a copy of the source PartialList by making - copies of all of the Partials in the source and adding them to - this PartialList. - */ -extern "C" -void partialList_copy( PartialList * dst, const PartialList * src ) -{ - try - { - ThrowIfNull((PartialList *) dst); - ThrowIfNull((PartialList *) src); - - debugger << "copying PartialList containing " << src->size() << " Partials" << endl; - *dst = *src; - } - catch( Exception & ex ) - { - std::string s("Loris exception in partialList_copy(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partialList_copy(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* partialList_size -/* -/* Return the number of Partials in this PartialList. - */ -extern "C" -unsigned long partialList_size( const PartialList * ptr_this ) -{ - try - { - ThrowIfNull((PartialList *) ptr_this); - return ptr_this->size(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partialList_size(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partialList_size(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return 0; -} - -/* ---------------------------------------------------------------- */ -/* partialList_splice -/* -/* Splice all the Partials in the source PartialList onto the end of - this PartialList, leaving the source empty. - */ -extern "C" -void partialList_splice( PartialList * dst, PartialList * src ) -{ - try - { - ThrowIfNull((PartialList *) dst); - ThrowIfNull((PartialList *) src); - - debugger << "splicing PartialList containing " << src->size() << " Partials" - << " into PartialList containing " << dst->size() << " Partials"<< endl; - dst->splice( dst->end(), *src ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partialList_splice(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partialList_splice(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* Partial object interface -/* -/* A Partial represents a single component in the - reassigned bandwidth-enhanced additive model. A Partial consists of a - chain of Breakpoints describing the time-varying frequency, amplitude, - and bandwidth (or noisiness) envelopes of the component, and a 4-byte - label. The Breakpoints are non-uniformly distributed in time. For more - information about Reassigned Bandwidth-Enhanced Analysis and the - Reassigned Bandwidth-Enhanced Additive Sound Model, refer to the Loris - website: www.cerlsoundgroup.org/Loris/. - */ - -/* ---------------------------------------------------------------- */ -/* partial_startTime -/* -/* Return the start time (seconds) for the specified Partial. - */ -double partial_startTime( const Partial * p ) -{ - double ret = 0; - try - { - ThrowIfNull((Partial *) p); - - ret = p->startTime(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_startTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_startTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* partial_endTime -/* -/* Return the end time (seconds) for the specified Partial. - */ -double partial_endTime( const Partial * p ) -{ - double ret = 0; - try - { - ThrowIfNull((Partial *) p); - - ret = p->endTime(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_endTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_endTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* partial_duration -/* -/* Return the duration (seconds) for the specified Partial. - */ -double partial_duration( const Partial * p ) -{ - double ret = 0; - try - { - ThrowIfNull((Partial *) p); - - ret = p->duration(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_duration(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_duration(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* partial_initialPhase -/* -/* Return the initial phase (radians) for the specified Partial. - */ -double partial_initialPhase( const Partial * p ) -{ - double ret = 0; - try - { - ThrowIfNull((Partial *) p); - - ret = p->initialPhase(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_initialPhase(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_initialPhase(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* partial_label -/* -/* Return the integer label for the specified Partial. - */ -int partial_label( const Partial * p ) -{ - int ret = 0; - try - { - ThrowIfNull((Partial *) p); - - ret = p->label(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_label(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_label(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* partial_numBreakpoints -/* -/* Return the number of Breakpoints in the specified Partial. - */ -unsigned long partial_numBreakpoints( const Partial * p ) -{ - unsigned long ret = 0; - try - { - ThrowIfNull((Partial *) p); - - ret = p->size(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_numBreakpoints(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_numBreakpoints(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* partial_frequencyAt -/* -/* Return the frequency (Hz) of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ -double partial_frequencyAt( const Partial * p, double t ) -{ - double ret = 0; - try - { - ThrowIfNull((Partial *) p); - - ret = p->frequencyAt( t ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_frequencyAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_frequencyAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* partial_bandwidthAt -/* -/* Return the bandwidth of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ -double partial_bandwidthAt( const Partial * p, double t ) -{ - double ret = 0; - try - { - ThrowIfNull((Partial *) p); - - ret = p->bandwidthAt( t ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_bandwidthAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_bandwidthAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* partial_phaseAt -/* -/* Return the phase (radians) of the specified Partial interpolated - at a particular time. It is an error to apply this function to - a Partial having no Breakpoints. - */ -double partial_phaseAt( const Partial * p, double t ) -{ - double ret = 0; - try - { - ThrowIfNull((Partial *) p); - - ret = p->phaseAt( t ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_phaseAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_phaseAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* partial_amplitudeAt -/* -/* Return the (absolute) amplitude of the specified Partial interpolated - at a particular time. Partials are assumed to fade out - over 1 millisecond at the ends (rather than instantaneously). - It is an error to apply this function to a Partial having no Breakpoints. - */ -double partial_amplitudeAt( const Partial * p, double t ) -{ - double ret = 0; - try - { - ThrowIfNull((Partial *) p); - - ret = p->amplitudeAt( t, 0.001 ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_amplitudeAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_amplitudeAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* partial_setLabel -/* -/* Assign a new integer label to the specified Partial. - */ -void partial_setLabel( Partial * p, int label ) -{ - try - { - ThrowIfNull((Partial *) p); - - p->setLabel( label ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in partial_setLabel(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in partial_setLabel(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* Breakpoint object interface -/* -/* A Breakpoint represents a single breakpoint in the - Partial parameter (frequency, amplitude, bandwidth) envelope. - Instantaneous phase is also stored, but is only used at the onset of - a partial, or when it makes a transition from zero to nonzero amplitude. - - Loris Partials represent reassigned bandwidth-enhanced model components. - A Partial consists of a chain of Breakpoints describing the time-varying - frequency, amplitude, and bandwidth (noisiness) of the component. - For more information about Reassigned Bandwidth-Enhanced - Analysis and the Reassigned Bandwidth-Enhanced Additive Sound - Model, refer to the Loris website: - www.cerlsoundgroup.org/Loris/. - */ - -/* ---------------------------------------------------------------- */ -/* breakpoint_getFrequency -/* -/* Return the frequency (Hz) of the specified Breakpoint. - */ -double breakpoint_getFrequency( const Breakpoint * bp ) -{ - double ret = 0; - try - { - ThrowIfNull((Breakpoint *) bp); - - ret = bp->frequency(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in breakpoint_getFrequency(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in breakpoint_getFrequency(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* breakpoint_getAmplitude -/* -/* Return the (absolute) amplitude of the specified Breakpoint. - */ -double breakpoint_getAmplitude( const Breakpoint * bp ) -{ - double ret = 0; - try - { - ThrowIfNull((Breakpoint *) bp); - - ret = bp->amplitude(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in breakpoint_getAmplitude(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in breakpoint_getAmplitude(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* breakpoint_getBandwidth -/* -/* Return the bandwidth coefficient of the specified Breakpoint. - */ -double breakpoint_getBandwidth( const Breakpoint * bp ) -{ - double ret = 0; - try - { - ThrowIfNull((Breakpoint *) bp); - - ret = bp->bandwidth(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in breakpoint_getBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in breakpoint_getBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* breakpoint_getPhase -/* -/* Return the phase (radians) of the specified Breakpoint. - */ -double breakpoint_getPhase( const Breakpoint * bp ) -{ - double ret = 0; - try - { - ThrowIfNull((Breakpoint *) bp); - - ret = bp->phase(); - } - catch( Exception & ex ) - { - std::string s("Loris exception in breakpoint_getPhase(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in breakpoint_getPhase(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - return ret; -} - -/* ---------------------------------------------------------------- */ -/* breakpoint_setFrequency -/* -/* Assign a new frequency (Hz) to the specified Breakpoint. - */ -void breakpoint_setFrequency( Breakpoint * bp, double f ) -{ - try - { - ThrowIfNull((Breakpoint *) bp); - - bp->setFrequency( f ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in breakpoint_setFrequency(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in breakpoint_setFrequency(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* breakpoint_setAmplitude -/* -/* Assign a new (absolute) amplitude to the specified Breakpoint. - */ -void breakpoint_setAmplitude( Breakpoint * bp, double a ) -{ - try - { - ThrowIfNull((Breakpoint *) bp); - - bp->setAmplitude( a ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in breakpoint_setAmplitude(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in breakpoint_setAmplitude(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* breakpoint_setBandwidth -/* -/* Assign a new bandwidth coefficient to the specified Breakpoint. - */ -void breakpoint_setBandwidth( Breakpoint * bp, double bw ) -{ - try - { - ThrowIfNull((Breakpoint *) bp); - - bp->setBandwidth( bw ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in breakpoint_setBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in breakpoint_setBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* breakpoint_setPhase -/* -/* Assign a new phase (radians) to the specified Breakpoint. - */ -void breakpoint_setPhase( Breakpoint * bp, double phi ) -{ - try - { - ThrowIfNull((Breakpoint *) bp); - - bp->setPhase( phi ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in breakpoint_setPhase(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in breakpoint_setPhase(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} diff --git a/loris_library/Source/src/lorisUtilities_pi.cpp b/loris_library/Source/src/lorisUtilities_pi.cpp deleted file mode 100644 index 0b401a4..0000000 --- a/loris_library/Source/src/lorisUtilities_pi.cpp +++ /dev/null @@ -1,1075 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * lorisUtilities_pi.C - * - * A component of the C-linkable procedural interface for Loris. - * - * Main components of the Loris procedural interface: - * - object interfaces - Analyzer, Synthesizer, Partial, PartialIterator, - * PartialList, PartialListIterator, Breakpoint, BreakpointEnvelope, - * and SampleVector need to be (opaque) objects in the interface, - * either because they hold state (e.g. Analyzer) or because they are - * fundamental data types (e.g. Partial), so they need a procedural - * interface to their member functions. All these things need to be - * opaque pointers for the benefit of C. - * - non-object-based procedures - other classes in Loris are not so stateful, - * and have sufficiently narrow functionality that they need only - * procedures, and no object representation. - * - utility functions - some procedures that are generally useful but are - * not yet part of the Loris core are also defined. - * - notification and exception handlers - all exceptions must be caught and - * handled internally, clients can specify an exception handler and - * a notification function (the default one in Loris uses printf()). - * - * This file defines the utility functions that are useful, and in many - * cases trivial in C++ (usign the STL for example) but are not represented - * by classes in the Loris core. - * - * Kelly Fitz, 10 Nov 2000 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "loris.h" -#include "lorisException_pi.h" - -#include "BreakpointEnvelope.h" -#include "LorisExceptions.h" -#include "Notifier.h" -#include "Partial.h" -#include "PartialUtils.h" - -#include -#include -#include -#include -#include -#include - -using namespace Loris; - -// --------------------------------------------------------------------------- -// Functors to help apply C-callbacks to lists of Partials -// by converting Partial references to pointer arguments. -// - -struct CallWithPointer : public std::unary_function< Partial, void > -{ - typedef void (* Func)( Partial *, void * ); - Func func; - void * data; - - CallWithPointer( Func f, void * d ) : func( f ), data( d ) {} - - void operator()( Partial & partial ) const - { - func( &partial, data ); - } -}; - -struct PredWithPointer : public std::unary_function< const Partial, bool > -{ - typedef int (* Pred)( const Partial *, void * ); - Pred pred; - void * data; - - PredWithPointer( Pred p, void * d ) : pred( p ), data( d ) {} - - bool operator()( const Partial & partial ) const - { - return 0 != pred( &partial, data ); - } -}; - -/* ---------------------------------------------------------------- */ -/* utility functions -/* -/* Operations for transforming and manipulating collections - of Partials. - */ - -/* ---------------------------------------------------------------- */ -/* avgAmplitude -/* -/* Return the average amplitude over all Breakpoints in this Partial. - Return zero if the Partial has no Breakpoints. - */ -extern "C" -double avgAmplitude( const Partial * p ) -{ - try - { - ThrowIfNull((Partial *) p); - return PartialUtils::avgAmplitude( *p ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in avgAmplitude(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in avgAmplitude(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - - return 0; -} - -/* ---------------------------------------------------------------- */ -/* avgFrequency -/* -/* Return the average frequency over all Breakpoints in this Partial. - Return zero if the Partial has no Breakpoints. - */ -extern "C" -double avgFrequency( const Partial * p ) -{ - try - { - ThrowIfNull((Partial *) p); - return PartialUtils::avgFrequency( *p ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in avgFrequency(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in avgFrequency(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - - return 0;} - - -/* ---------------------------------------------------------------- */ -/* copyIf -/* -/* Append copies of Partials in the source PartialList satisfying the - specified predicate to the destination PartialList. The source list - is unmodified. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ -extern "C" -void copyIf( const PartialList * src, PartialList * dst, - int ( * predicate )( const Partial * p, void * data ), - void * data ) -{ - try - { - ThrowIfNull((PartialList *) src); - ThrowIfNull((PartialList *) dst); - - std::remove_copy_if( src->begin(), src->end(), std::back_inserter( *dst ), - std::not1( PredWithPointer( predicate, data ) ) ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in copyIf(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in copyIf(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* copyLabeled -/* -/* Append copies of Partials in the source PartialList having the - specified label to the destination PartialList. The source list - is unmodified. - */ -extern "C" -void copyLabeled( const PartialList * src, long label, PartialList * dst ) -{ - try - { - ThrowIfNull((PartialList *) src); - ThrowIfNull((PartialList *) dst); - - std::remove_copy_if( src->begin(), src->end(), std::back_inserter( *dst ), - std::not1( PartialUtils::isLabelEqual(label) ) ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in copyLabeled(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in copyLabeled(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* crop -/* -/* Trim Partials by removing Breakpoints outside a specified time span. - Insert a Breakpoint at the boundary when cropping occurs. Remove - any Partials that are left empty after cropping (Partials having no - Breakpoints between t1 and t2). - */ -extern "C" -void crop( PartialList * partials, double t1, double t2 ) -{ - try - { - ThrowIfNull((PartialList *) partials); - - notifier << "cropping " << partials->size() << " Partials" << endl; - - PartialUtils::crop( partials->begin(), partials->end(), t1, t2 ); - - // remove empty Partials: - PartialList::iterator it = partials->begin(); - while ( it != partials->end() ) - { - if ( 0 == it->numBreakpoints() ) - { - it = partials->erase( it ); - } - else - { - ++it; - } - } - } - catch( Exception & ex ) - { - std::string s("Loris exception in crop(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in crop(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* extractIf -/* -/* Remove Partials in the source PartialList satisfying the - specified predicate from the source list and append them to - the destination PartialList. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ -extern "C" -void extractIf( PartialList * src, PartialList * dst, - int ( * predicate )( const Partial * p, void * data ), - void * data ) -{ - try - { - ThrowIfNull((PartialList *) src); - ThrowIfNull((PartialList *) dst); - - /* - std::list< Partial >::iterator it = - std::stable_partition( src->begin(), src->end(), - std::not1( PredWithPointer( predicate, data ) ) ); - - stable_partition should work, but seems sometimes to hang, - especially when there are lots and lots of Partials. Do it - efficiently by hand instead. - - dst->splice( dst->end(), *src, it, src->end() ); - */ - std::list< Partial >::iterator it; - for ( it = std::find_if( src->begin(), src->end(), PredWithPointer( predicate, data ) ); - it != src->end(); - it = std::find_if( it, src->end(), PredWithPointer( predicate, data ) ) ) - { - // the iterator passed to splice is a copy of it - // before the increment, so it is not corrupted - // by the splice, it is advanced to the next - // position before the splice is performed. - dst->splice( dst->end(), *src, it++ ); - } - - } - catch( Exception & ex ) - { - std::string s("Loris exception in extractIf(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in extractIf(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* extractLabeled -/* -/* Remove Partials in the source PartialList having the specified - label from the source list and append them to the destination - PartialList. - */ -extern "C" -void extractLabeled( PartialList * src, long label, PartialList * dst ) -{ - try - { - ThrowIfNull((PartialList *) src); - ThrowIfNull((PartialList *) dst); - - /* - std::list< Partial >::iterator it = - std::stable_partition( src->begin(), src->end(), - std::not1( PartialUtils::isLabelEqual(label) ) ); - - stable_partition should work, but seems sometimes to hang, - especially when there are lots and lots of Partials. Do it - efficiently by hand instead. - - dst->splice( dst->end(), *src, it, src->end() ); - */ - std::list< Partial >::iterator it; - for ( it = std::find_if( src->begin(), src->end(), PartialUtils::isLabelEqual(label) ); - it != src->end(); - it = std::find_if( it, src->end(), PartialUtils::isLabelEqual(label) ) ) - { - // the iterator passed to splice is a copy of it - // before the increment, so it is not corrupted - // by the splice, it is advanced to the next - // position before the splice is performed. - dst->splice( dst->end(), *src, it++ ); - } - } - catch( Exception & ex ) - { - std::string s("Loris exception in extractLabeled(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in extractLabeled(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* fixPhaseAfter -/* -/* Recompute phases of all Breakpoints later than the specified - time so that the synthesized phases of those later Breakpoints - matches the stored phase, as long as the synthesized phase at - the specified time matches the stored (not recomputed) phase. - - Phase fixing is only applied to non-null (nonzero-amplitude) - Breakpoints, because null Breakpoints are interpreted as phase - reset points in Loris. If a null is encountered, its phase is - simply left unmodified, and future phases wil be recomputed - from that one. - */ -extern "C" -void fixPhaseAfter( PartialList * partials, double time ) -{ - try - { - ThrowIfNull((PartialList *) partials); - PartialUtils::fixPhaseAfter( partials->begin(), partials->end(), time ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in fixPhaseAfter(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in fixPhaseAfter(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* fixPhaseAt -/* -/* Recompute phases of all Breakpoints in a Partial - so that the synthesized phases match the stored phases, - and the synthesized phase at (nearest) the specified - time matches the stored (not recomputed) phase. - - Backward phase-fixing stops if a null (zero-amplitude) - Breakpoint is encountered, because nulls are interpreted as - phase reset points in Loris. If a null is encountered, the - remainder of the Partial (the front part) is fixed in the - forward direction, beginning at the start of the Partial. - Forward phase fixing is only applied to non-null - (nonzero-amplitude) Breakpoints. If a null is encountered, - its phase is simply left unmodified, and future phases wil be - recomputed from that one. - */ -extern "C" -void fixPhaseAt( PartialList * partials, double time ) -{ - try - { - ThrowIfNull((PartialList *) partials); - PartialUtils::fixPhaseAt( partials->begin(), partials->end(), time ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in fixPhaseAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in fixPhaseAt(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* fixPhaseBefore -/* -/* Recompute phases of all Breakpoints earlier than the specified - time so that the synthesized phases of those earlier Breakpoints - matches the stored phase, and the synthesized phase at the - specified time matches the stored (not recomputed) phase. - - Backward phase-fixing stops if a null (zero-amplitude) Breakpoint - is encountered, because nulls are interpreted as phase reset - points in Loris. If a null is encountered, the remainder of the - Partial (the front part) is fixed in the forward direction, - beginning at the start of the Partial. - */ -extern "C" -void fixPhaseBefore( PartialList * partials, double time ) -{ - try - { - ThrowIfNull((PartialList *) partials); - PartialUtils::fixPhaseBefore( partials->begin(), partials->end(), time ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in fixPhaseBefore(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in fixPhaseBefore(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* fixPhaseBetween -/* - Fix the phase travel between two times by adjusting the - frequency and phase of Breakpoints between those two times. - - This algorithm assumes that there is nothing interesting - about the phases of the intervening Breakpoints, and modifies - their frequencies as little as possible to achieve the correct - amount of phase travel such that the frequencies and phases at - the specified times match the stored values. The phases of all - the Breakpoints between the specified times are recomputed. - */ -extern "C" -void fixPhaseBetween( PartialList * partials, double tbeg, double tend ) -{ - try - { - ThrowIfNull((PartialList *) partials); - PartialUtils::fixPhaseBetween( partials->begin(), partials->end(), - tbeg, tend ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in fixPhaseBetween(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in fixPhaseBetween(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - - -/* ---------------------------------------------------------------- */ -/* fixPhaseForward -/* -/* Recompute phases of all Breakpoints later than the specified - time so that the synthesized phases of those later Breakpoints - matches the stored phase, as long as the synthesized phase at - the specified time matches the stored (not recomputed) phase. - Breakpoints later than tend are unmodified. - - Phase fixing is only applied to non-null (nonzero-amplitude) - Breakpoints, because null Breakpoints are interpreted as phase - reset points in Loris. If a null is encountered, its phase is - simply left unmodified, and future phases wil be recomputed - from that one. - */ -extern "C" -void fixPhaseForward( PartialList * partials, double tbeg, double tend ) -{ - try - { - ThrowIfNull((PartialList *) partials); - PartialUtils::fixPhaseForward( partials->begin(), partials->end(), - tbeg, tend ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in fixPhaseForward(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in fixPhaseForward(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - - -/* ---------------------------------------------------------------- */ -/* forEachBreakpoint -/* -/* Apply a function to each Breakpoint in a Partial. The function - is called once for each Breakpoint in the source Partial. The - function may modify the Breakpoint (but should not otherwise attempt - to modify the Partial). The data parameter can be used to supply extra - user-defined data to the function. Pass 0 if no additional data is needed. - The function should return 0 if successful. If the function returns - a non-zero value, then forEachBreakpoint immediately returns that value - without applying the function to any other Breakpoints in the Partial. - forEachBreakpoint returns zero if all calls to func return zero. - */ -int forEachBreakpoint( Partial * p, - int ( * func )( Breakpoint * p, double time, void * data ), - void * data ) -{ - int result = 0; - try - { - ThrowIfNull((Partial *) p); - - Partial::iterator it; - for ( it = p->begin(); 0 == result && it != p->end(); ++it ) - { - result = func( &(it.breakpoint()), it.time(), data ); - } - } - catch( Exception & ex ) - { - std::string s("Loris exception in forEachBreakpoint(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in forEachBreakpoint(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - - return result; -} - - -/* ---------------------------------------------------------------- */ -/* forEachPartial -/* -/* Apply a function to each Partial in a PartialList. The function - is called once for each Partial in the source PartialList. The - function may modify the Partial (but should not attempt to modify - the PartialList). The data parameter can be used to supply extra - user-defined data to the function. Pass 0 if no additional data - is needed. The function should return 0 if successful. If the - function returns a non-zero value, then forEachPartial immediately - returns that value without applying the function to any other - Partials in the PartialList. forEachPartial returns zero if all - calls to func return zero. - */ -int forEachPartial( PartialList * src, - int ( * func )( Partial * p, void * data ), - void * data ) -{ - int result = 0; - try - { - ThrowIfNull((PartialList *) src); - - PartialList::iterator it; - for ( it = src->begin(); 0 == result && it != src->end(); ++it ) - { - result = func( &(*it), data ); - } - } - catch( Exception & ex ) - { - std::string s("Loris exception in forEachPartial(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in forEachPartial(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - - return result; -} - - -/* ---------------------------------------------------------------- */ -/* peakAmplitude -/* -/* Return the maximum amplitude achieved by a Partial. - */ -extern "C" -double peakAmplitude( const Partial * p ) -{ - try - { - ThrowIfNull((Partial *) p); - return PartialUtils::peakAmplitude( *p ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in peakAmplitude(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in peakAmplitude(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - - return 0; -} - -/* ---------------------------------------------------------------- */ -/* removeIf -/* -/* Remove from a PartialList all Partials satisfying the - specified predicate. The data parameter can be used to - supply extra user-defined data to the function. Pass 0 if no - additional data is needed. - */ -extern "C" -void removeIf( PartialList * src, - int ( * predicate )( const Partial * p, void * data ), - void * data ) -{ - try - { - ThrowIfNull((PartialList *) src); - std::list< Partial >::iterator it = - std::remove_if( src->begin(), src->end(), - PredWithPointer( predicate, data ) ); - src->erase( it, src->end() ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in removeIf(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in removeIf(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - - -/* ---------------------------------------------------------------- */ -/* removeLabeled -/* -/* Remove from a PartialList all Partials having the specified label. - */ -extern "C" -void removeLabeled( PartialList * src, long label ) -{ - try - { - ThrowIfNull((PartialList *) src); - std::list< Partial >::iterator it = - std::remove_if( src->begin(), src->end(), - PartialUtils::isLabelEqual( label ) ); - src->erase( it, src->end() ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in removeLabeled(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in removeLabeled(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* scaleAmp -/* -/* Bad old name for scaleAmplitude. - */ -extern "C" -void scaleAmp( PartialList * partials, BreakpointEnvelope * ampEnv ) -{ - scaleAmplitude( partials, ampEnv ); -} - -/* ---------------------------------------------------------------- */ -/* scaleAmplitude -/* -/* Scale the amplitude of the Partials in a PartialList according - to an envelope representing a time-varying amplitude scale value. - */ -extern "C" -void scaleAmplitude( PartialList * partials, BreakpointEnvelope * ampEnv ) -{ - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((BreakpointEnvelope *) ampEnv); - - notifier << "scaling amplitude of " << partials->size() << " Partials" << endl; - - PartialUtils::scaleAmplitude( partials->begin(), partials->end(), *ampEnv ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in scaleAmplitude(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in scaleAmplitude(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* scaleBandwidth -/* -/* Scale the bandwidth of the Partials in a PartialList according - to an envelope representing a time-varying bandwidth scale value. - */ -extern "C" -void scaleBandwidth( PartialList * partials, BreakpointEnvelope * bwEnv ) -{ - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((BreakpointEnvelope *) bwEnv); - - notifier << "scaling bandwidth of " << partials->size() << " Partials" << endl; - - PartialUtils::scaleBandwidth( partials->begin(), partials->end(), *bwEnv ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in scaleBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in scaleBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* setBandwidth -/* -/* Assign the bandwidth of the Partials in a PartialList according - to an envelope representing a time-varying bandwidth scale value. - */ -extern "C" -void setBandwidth( PartialList * partials, BreakpointEnvelope * bwEnv ) -{ - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((BreakpointEnvelope *) bwEnv); - - notifier << "setting bandwidth of " << partials->size() << " Partials" << endl; - - PartialUtils::setBandwidth( partials->begin(), partials->end(), *bwEnv ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in setBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in setBandwidth(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* scaleFrequency -/* -/* Scale the frequency of the Partials in a PartialList according - to an envelope representing a time-varying frequency scale value. - */ -extern "C" -void scaleFrequency( PartialList * partials, BreakpointEnvelope * freqEnv ) -{ - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((BreakpointEnvelope *) freqEnv); - - notifier << "scaling frequency of " << partials->size() << " Partials" << endl; - - PartialUtils::scaleFrequency( partials->begin(), partials->end(), *freqEnv ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in scaleFrequency(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in scaleFrequency(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* scaleNoiseRatio -/* -/* Scale the relative noise content of the Partials in a PartialList - according to an envelope representing a (time-varying) noise energy - scale value. - */ -extern "C" -void scaleNoiseRatio( PartialList * partials, BreakpointEnvelope * noiseEnv ) -{ - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((BreakpointEnvelope *) noiseEnv); - - notifier << "scaling noise ratio of " << partials->size() << " Partials" << endl; - - PartialUtils::scaleNoiseRatio( partials->begin(), partials->end(), *noiseEnv ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in scaleNoiseRatio(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in scaleNoiseRatio(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* shiftPitch -/* -/* Shift the pitch of all Partials in a PartialList according to - the given pitch envelope. The pitch envelope is assumed to have - units of cents (1/100 of a halfstep). - */ -extern "C" -void shiftPitch( PartialList * partials, BreakpointEnvelope * pitchEnv ) -{ - try - { - ThrowIfNull((PartialList *) partials); - ThrowIfNull((BreakpointEnvelope *) pitchEnv); - - notifier << "shifting pitch of " << partials->size() << " Partials" << endl; - - PartialUtils::shiftPitch( partials->begin(), partials->end(), *pitchEnv ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in shiftPitch(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in shiftPitch(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* shiftTime -/* -/* Shift the time of all the Breakpoints in all Partials in a - PartialList by a constant amount. - */ -extern "C" -void shiftTime( PartialList * partials, double offset ) -{ - try - { - ThrowIfNull((PartialList *) partials); - - notifier << "shifting time of " << partials->size() << " Partials" << endl; - - PartialUtils::shiftTime( partials->begin(), partials->end(), offset ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in shiftTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in shiftTime(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } -} - -/* ---------------------------------------------------------------- */ -/* sortByLabel -/* -/* Sort the Partials in a PartialList in order of increasing label. - * The sort is stable; Partials having the same label are not - * reordered. - */ -extern "C" -void sortByLabel( PartialList * partials ) -{ - partials->sort( PartialUtils::compareLabelLess() ); -} - -/* ---------------------------------------------------------------- */ -/* timeSpan -/* -/* Return the minimum start time and maximum end time - * in seconds of all Partials in this PartialList. The v - * times are returned in the (non-null) pointers tmin - * and tmax. - */ -extern "C" -void timeSpan( PartialList * partials, double * tmin, double * tmax ) -{ - std::pair< double, double > times = - PartialUtils::timeSpan( partials->begin(), partials->end() ); - if ( 0 != tmin ) - { - *tmin = times.first; - } - if ( 0 != tmax ) - { - *tmax = times.second; - } -} - -/* ---------------------------------------------------------------- */ -/* weightedAvgFrequency -/* -/* Return the average frequency over all Breakpoints in this Partial, - weighted by the Breakpoint amplitudes. Return zero if the Partial - has no Breakpoints. - */ -extern "C" -double weightedAvgFrequency( const Partial * p ) -{ - try - { - ThrowIfNull((Partial *) p); - return PartialUtils::weightedAvgFrequency( *p ); - } - catch( Exception & ex ) - { - std::string s("Loris exception in weightedAvgFrequency(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - catch( std::exception & ex ) - { - std::string s("std C++ exception in weightedAvgFrequency(): " ); - s.append( ex.what() ); - handleException( s.c_str() ); - } - - return 0; -} diff --git a/loris_library/Source/src/phasefix.cpp b/loris_library/Source/src/phasefix.cpp deleted file mode 100644 index b26deab..0000000 --- a/loris_library/Source/src/phasefix.cpp +++ /dev/null @@ -1,470 +0,0 @@ -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * phasefix.C - * - * Implements a phase correction algorithm that perturbs slightly the - * frequencies or Breakpoints in a Partial so that the rendered Partial - * will achieve (or be closer to) the analyzed Breakpoint phases. - * - * Kelly Fitz, 23 Sept 04 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include "phasefix.h" - -#include "Breakpoint.h" -#include "BreakpointUtils.h" -#include "LorisExceptions.h" -#include "Notifier.h" -#include "Partial.h" - - -#include -#include -#include -#include - -#if defined(HAVE_M_PI) && (HAVE_M_PI) - const double Pi = M_PI; -#else - const double Pi = 3.14159265358979324; -#endif - - -// begin namespace -namespace Loris { - -// -- local helpers -- - - -// --------------------------------------------------------------------------- -// wrapPi -// Wrap an unwrapped phase value to the range [-pi,pi] using -// O'Donnell's phase wrapping function. -// -double wrapPi( double x ) -{ - using namespace std; // floor should be in std - #define ROUND(x) (floor(.5 + (x))) - const double TwoPi = 2.0*Pi; - return x + ( TwoPi * ROUND(-x/TwoPi) ); -} - - - -// --------------------------------------------------------------------------- -// phaseTravel -// -// Compute the sinusoidal phase travel between two Breakpoints. -// Return the total unwrapped phase travel. -// -double phaseTravel( const Breakpoint & bp0, const Breakpoint & bp1, - double dt ) -{ - double f0 = bp0.frequency(); - double f1 = bp1.frequency(); - double favg = .5 * ( f0 + f1 ); - return 2 * Pi * favg * dt; -} - -// --------------------------------------------------------------------------- -// phaseTravel -// -// Compute the sinusoidal phase travel between two Breakpoints. -// Return the total unwrapped phase travel. -// -static double phaseTravel( Partial::const_iterator bp0, Partial::const_iterator bp1 ) -{ - return phaseTravel( bp0.breakpoint(), bp1.breakpoint(), - bp1.time() - bp0.time() ); -} - -// -- phase correction -- - -// --------------------------------------------------------------------------- -// fixPhaseBackward -// -//! Recompute phases of all Breakpoints on the half-open range [stopHere, pos) -//! so that the synthesized phases of those Breakpoints matches -//! the stored phase, as long as the synthesized phase at stopHere -//! matches the stored (not recomputed) phase. -//! -//! The phase is corrected beginning at the end of the range, maintaining -//! the stored phase in the Breakpoint at pos. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the range -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the stopHere. -//! -//! \pre pos and stopHere are iterators on the same Partial, and -//! pos must be not later than stopHere. -//! \pre pos cannot be end of the Partial, it must be the postion -//! of a valid Breakpoint. -//! \param stopHere the position of the earliest Breakpoint whose phase might be -//! recomputed. -//! \param pos the position of a (later) Breakpoint whose phase is to be matched. -//! The phase at pos is not modified. -// -void fixPhaseBackward( Partial::iterator stopHere, Partial::iterator pos ) -{ - while ( pos != stopHere && - BreakpointUtils::isNonNull( pos.breakpoint() ) ) - { - // pos is not the first Breakpoint in the Partial, - // and pos is not a Null Breakpoint. - // Compute the correct phase for the - // predecessor of pos. - Partial::iterator posFwd = pos--; - double travel = phaseTravel( pos, posFwd ); - pos.breakpoint().setPhase( wrapPi( posFwd.breakpoint().phase() - travel ) ); - } - - // if a null was encountered, then stop fixing backwards, - // and fix the front of the Partial in the forward direction: - if ( pos != stopHere ) - { - // pos is not the first Breakpoint in the Partial, - // and it is a Null Breakpoint (zero amplitude), - // so it will be used to reset the phase during - // synthesis. - // The phase of all Breakpoints starting with pos - // and ending with the Breakpoint nearest to time t - // has been corrected. - // Fix phases before pos starting at the beginning - // of the Partial. - // - // Dont fix pos, it has already been fixed. - fixPhaseForward( stopHere, --pos ); - } -} - -// ----------------------------------------------------------------------- ---- -// fixPhaseForward -// -//! Recompute phases of all Breakpoints on the closed range [pos, stopHere] -//! so that the synthesized phases of those Breakpoints matches -//! the stored phase, as long as the synthesized phase at pos -//! matches the stored (not recomputed) phase. The phase at pos -//! is modified only if pos is the position of a null Breakpoint -//! and the Breakpoint that follows is non-null. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is corrected from its non-Null -//! successor, if it has one, otherwise it is unmodified. -//! -//! \pre pos and stopHere are iterators on the same Partial, and -//! pos must be not later than stopHere. -//! \pre stopHere cannot be end of the Partial, it must be the postion -//! of a valid Breakpoint. -//! \param pos the position of the first Breakpoint whose phase might be -//! recomputed. -//! \param stopHere the position of the last Breakpoint whose phase might -//! be modified. -// -void fixPhaseForward( Partial::iterator pos, Partial::iterator stopHere ) -{ - while ( pos != stopHere ) - { - Partial::iterator posPrev = pos++; - - // update phase based on the phase travel between - // posPrev and pos UNLESS pos is Null: - if ( BreakpointUtils::isNonNull( pos.breakpoint() ) ) - { - // pos is the position of a non-Null Breakpoint, - // posPrev is its predecessor: - double travel = phaseTravel( posPrev, pos ); - - if ( BreakpointUtils::isNonNull( posPrev.breakpoint() ) ) - { - // if its predecessor of pos is non-Null, then fix - // the phase of the Breakpoint at pos. - pos.breakpoint().setPhase( wrapPi( posPrev.breakpoint().phase() + travel ) ); - } - else - { - // if the predecessor of pos is Null, then - // correct the predecessor's phase so that - // it correctly resets the synthesis phase - // so that the phase of the Breakpoint at - // pos is achieved in synthesis. - posPrev.breakpoint().setPhase( wrapPi( pos.breakpoint().phase() - travel ) ); - } - } - } -} - - -// --------------------------------------------------------------------------- -// fixPhaseBetween -// -//! Fix the phase travel between two Breakpoints by adjusting the -//! frequency and phase of Breakpoints between those two. -//! -//! This algorithm assumes that there is nothing interesting about the -//! phases of the intervening Breakpoints, and modifies their frequencies -//! as little as possible to achieve the correct amount of phase travel -//! such that the frequencies and phases at the specified times -//! match the stored values. The phases of all the Breakpoints between -//! the specified times are recomputed. -//! -//! Null Breakpoints are treated the same as non-null Breakpoints. -//! -//! \pre b and e are iterators on the same Partials, and -//! e must not preceed b in that Partial. -//! \pre There must be at least one Breakpoint in the -//! Partial between b and e. -//! \post The phases and frequencies of the Breakpoints in the -//! range have been recomputed such that an oscillator -//! initialized to the parameters of the first Breakpoint -//! will arrive at the parameters of the last Breakpoint, -//! and all the intervening Breakpoints will be matched. -//! \param b The phases and frequencies of Breakpoints later than -//! this one may be modified. -//! \param e The phases and frequencies of Breakpoints earlier than -//! this one may be modified. -// -void fixPhaseBetween( Partial::iterator b, Partial::iterator e ) -{ - if ( 1 < std::distance( b, e ) ) - { - // Accumulate the actual phase travel over the Breakpoint - // span, and count the envelope segments. - double travel = 0; - Partial::iterator next = b; - do - { - Partial::iterator prev = next++; - travel += phaseTravel( prev, next ); - } while( next != e ); - - // Compute the desired amount of phase travel: - double deviation = wrapPi( e.breakpoint().phase() - ( b.breakpoint().phase() + travel ) ); - double desired = travel + deviation; - - // Compute the amount by which to perturb the frequencies of - // all the null Breakpoints between b and e. - // - // The accumulated phase travel is the sum of the average frequency - // (in radians) of each segment times the duration of each segment - // (the actual phase travel is computed this way). If this sum is - // computed with each Breakpoint frequency perturbed (additively) - // by delta, and set equal to the desired phase travel, then it - // can be simplified to: - // delta = 2 * ( phase error ) / ( tN + tN-1 - t1 - t0 ) - // where tN is the time of e, tN-1 is the time of its predecessor, - // t0 is the time of b, and t1 is the time of b's successor. - // - Partial::iterator iter = b; - double t0 = iter.time(); - ++iter; - double t1 = iter.time(); - iter = e; - double tN = iter.time(); - --iter; - double tNm1 = iter.time(); - - Assert( t1 < tN ); // else there were no Breakpoints in between - - double delta = ( 2 * ( desired - travel ) / ( tN + tNm1 - t1 - t0 ) ) / ( 2 * Pi ); - - // Perturb the Breakpoint frequencies. - next = b; - Partial::iterator prev = next++; - while ( next != e ) - { - next.breakpoint().setFrequency( next.breakpoint().frequency() + delta ); - - double newtravel = phaseTravel( prev, next ); - next.breakpoint().setPhase( wrapPi( prev.breakpoint().phase() + newtravel ) ); - - prev = next++; - } - } - else - { - // Preconditions not met, cannot fix the phase travel. - // Should raise exception? - debugger << "cannot fix phase between " << b.time() << " and " << e.time() - << ", there are no Breakpoints between those times" << endl; - } - -} - -// --------------------------------------------------------------------------- -// matchPhaseFwd -// -//! Compute the target frequency that will affect the -//! predicted (by the Breakpoint phases) amount of -//! sinusoidal phase travel between two breakpoints, -//! and assign that frequency to the target Breakpoint. -//! After computing the new frequency, update the phase of -//! the later Breakpoint. -//! -//! If the earlier Breakpoint is null and the later one -//! is non-null, then update the phase of the earlier -//! Breakpoint, and do not modify its frequency or the -//! later Breakpoint. -//! -//! The most common kinds of errors are local (or burst) errors in -//! frequency and phase. These errors are best corrected by correcting -//! less than half the detected error at any time. Correcting more -//! than that will produce frequency oscillations for the remainder of -//! the Partial, in the case of a single bad frequency (as is common -//! at the onset of a tone). Any damping factor less then one will -//! converge eventually, .5 or less will converge without oscillating. -//! Use the damping argument to control the damping of the correction. -//! Specify 1 for no damping. -//! -//! \pre The two Breakpoints are assumed to be consecutive in -//! a Partial. -//! \param bp0 The earlier Breakpoint. -//! \param bp1 The later Breakpoint. -//! \param dt The time (in seconds) between bp0 and bp1. -//! \param damping The fraction of the amount of phase error that will -//! be corrected (.5 or less will prevent frequency oscilation -//! due to burst errors in phase). -//! \param maxFixPct The maximum amount of frequency adjustment -//! that can be made to the frequency of bp1, expressed -//! as a precentage of the unmodified frequency of bp1. -//! If the necessary amount of frequency adjustment exceeds -//! this amount, then the phase will not be matched, -//! but will be updated as well to be consistent with -//! the frequencies. (default is 0.2%) -// -void matchPhaseFwd( Breakpoint & bp0, Breakpoint & bp1, - double dt, double damping, double maxFixPct ) -{ - double travel = phaseTravel( bp0, bp1, dt ); - - if ( ! BreakpointUtils::isNonNull( bp1 ) ) - { - // if bp1 is null, DON'T compute a new phase, - // because Nulls are phase reset points. - - // bp1.setPhase( wrapPi( bp0.phase() + travel ) ); - } - else if ( ! BreakpointUtils::isNonNull( bp0 ) ) - { - // if bp0 is null, and bp1 is not, then bp0 - // should be a phase reset Breakpoint during - // rendering, so compute a new phase for - // bp0 that achieves bp1's phase. - bp0.setPhase( wrapPi( bp1.phase() - travel ) ) ; - } - else - { - // invariant: - // neither bp0 nor bp1 is null - // - // modify frequecies to match phases as nearly as possible - double err = wrapPi( bp1.phase() - ( bp0.phase() + travel ) ); - - // The most common kinds of errors are local (or burst) errors in - // frequency and phase. These errors are best corrected by correcting - // less than half the detected error at any time. Correcting more - // than that will produce frequency oscillations for the remainder of - // the Partial, in the case of a single bad frequency (as is common - // at the onset of a tone). Any damping factor less then one will - // converge eventually, .5 or less will converge without oscillating. - // #define DAMPING .5 - travel += damping * err; - - double f0 = bp0.frequency(); - double ftgt = ( travel / ( Pi * dt ) ) - f0; - - #ifdef Loris_Debug - debugger << "matchPhaseFwd: correcting " << bp1.frequency() << " to " << ftgt - << " (phase " << wrapPi( bp1.phase() ) << "), "; - #endif - - // If the target is not a null breakpoint, may need to - // clamp the amount of frequency modification. - if ( ftgt > bp1.frequency() * ( 1 + (maxFixPct*.01) ) ) - { - ftgt = bp1.frequency() * ( 1 + (maxFixPct*.01) ); - } - else if ( ftgt < bp1.frequency() * ( 1 - (maxFixPct*.01) ) ) - { - ftgt = bp1.frequency() * ( 1 - (maxFixPct*.01) ); - } - - bp1.setFrequency( ftgt ); - - // Recompute the phase according to the new frequency. - double phi = wrapPi( bp0.phase() + phaseTravel( bp0, bp1, dt ) ); - bp1.setPhase( phi ); - - #ifdef Loris_Debug - debugger << "achieved " << ftgt << " (phase " << phi << ")" << endl; - #endif - } -} - -// --------------------------------------------------------------------------- -// fixFrequency -// -//! Adjust frequencies of the Breakpoints in the -//! specified Partial such that the rendered Partial -//! achieves (or matches as nearly as possible, within -//! the constraint of the maximum allowable frequency -//! alteration) the analyzed phases. -//! -//! This just iterates over the Partial calling -//! matchPhaseFwd, should probably name those similarly. -//! -//! \param partial The Partial whose frequencies, -//! and possibly phases (if the frequencies -//! cannot be sufficiently altered to match -//! the phases), will be recomputed. -//! \param maxFixPct The maximum allowable frequency -//! alteration, default is 0.2%. -// -void fixFrequency( Partial & partial, double maxFixPct ) -{ - if ( partial.numBreakpoints() > 1 ) - { - Partial::iterator next = partial.begin(); - Partial::iterator prev = next++; - while ( next != partial.end() ) - { - if ( BreakpointUtils::isNonNull( next.breakpoint() ) ) - { - matchPhaseFwd( prev.breakpoint(), next.breakpoint(), - next.time() - prev.time(), 0.5, maxFixPct ); - } - prev = next++; - } - } -} - -} // end of namespace Loris diff --git a/loris_library/Source/src/phasefix.h b/loris_library/Source/src/phasefix.h deleted file mode 100644 index 016983d..0000000 --- a/loris_library/Source/src/phasefix.h +++ /dev/null @@ -1,237 +0,0 @@ -#ifndef PHASEFIX_H -#define PHASEFIX_H -/* - * This is the Loris C++ Class Library, implementing analysis, - * manipulation, and synthesis of digitized sounds using the Reassigned - * Bandwidth-Enhanced Additive Sound Model. - * - * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * phasefix.h - * - * Functions for correcting Breakpoint phases and frequencies so that - * stored phases match the phases that would be synthesized using the - * Loris Synthesizer. - * - * Kelly Fitz, 23 Sept 04 - * loris@cerlsoundgroup.org - * - * http://www.cerlsoundgroup.org/Loris/ - * - */ -#include "Partial.h" - -// begin namespace -namespace Loris { - -// FUNCTION PROTOYPES - -// fixPhaseBackward -// -//! Recompute phases of all Breakpoints on the half-open range [stopHere, pos) -//! so that the synthesized phases of those Breakpoints matches -//! the stored phase, as long as the synthesized phase at stopHere -//! matches the stored (not recomputed) phase. -//! -//! The phase is corrected beginning at the end of the range, maintaining -//! the stored phase in the Breakpoint at pos. -//! -//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint -//! is encountered, because nulls are interpreted as phase reset points -//! in Loris. If a null is encountered, the remainder of the range -//! (the front part) is fixed in the forward direction, beginning at -//! the start of the stopHere. -//! -//! \pre pos and stopHere are iterators on the same Partial, and -//! pos must be not later than stopHere. -//! \pre pos cannot be end of the Partial, it must be the postion -//! of a valid Breakpoint. -//! \param stopHere the position of the earliest Breakpoint whose phase might be -//! recomputed. -//! \param pos the position of a (later) Breakpoint whose phase is to be matched. -//! The phase at pos is not modified. -// -void fixPhaseBackward( Partial::iterator stopHere, Partial::iterator pos ); - -// fixPhaseForward -// -//! Recompute phases of all Breakpoints on the closed range [pos, stopHere] -//! so that the synthesized phases of those Breakpoints matches -//! the stored phase, as long as the synthesized phase at pos -//! matches the stored (not recomputed) phase. The phase at pos -//! is modified only if pos is the position of a null Breakpoint -//! and the Breakpoint that follows is non-null. -//! -//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, -//! because null Breakpoints are interpreted as phase reset points in -//! Loris. If a null is encountered, its phase is corrected from its non-Null -//! successor, if it has one, otherwise it is unmodified. -//! -//! \pre pos and stopHere are iterators on the same Partial, and -//! pos must be not later than stopHere. -//! \pre stopHere cannot be end of the Partial, it must be the postion -//! of a valid Breakpoint. -//! \param pos the position of the first Breakpoint whose phase might be -//! recomputed. -//! \param stopHere the position of the last Breakpoint whose phase might -//! be modified. -// -void fixPhaseForward( Partial::iterator pos, Partial::iterator stopHere ); - -// --------------------------------------------------------------------------- -// fixPhaseBetween -// -//! Fix the phase travel between two Breakpoints by adjusting the -//! frequency and phase of Breakpoints between those two. -//! -//! This algorithm assumes that there is nothing interesting about the -//! phases of the intervening Breakpoints, and modifies their frequencies -//! as little as possible to achieve the correct amount of phase travel -//! such that the frequencies and phases at the specified times -//! match the stored values. The phases of all the Breakpoints between -//! the specified times are recomputed. -//! -//! Null Breakpoints are treated the same as non-null Breakpoints. -//! -//! \pre b and e are iterators on the same Partials, and -//! e must not preceed b in that Partial. -//! \pre There must be at least one Breakpoint in the -//! Partial between b and e. -//! \post The phases and frequencies of the Breakpoints in the -//! range have been recomputed such that an oscillator -//! initialized to the parameters of the first Breakpoint -//! will arrive at the parameters of the last Breakpoint, -//! and all the intervening Breakpoints will be matched. -//! \param b The phases and frequencies of Breakpoints later than -//! this one may be modified. -//! \param e The phases and frequencies of Breakpoints earlier than -//! this one may be modified. -// -void fixPhaseBetween( Partial::iterator b, Partial::iterator e ); - -// fixFrequency -// -//! Adjust frequencies of the Breakpoints in the -//! specified Partial such that the rendered Partial -//! achieves (or matches as nearly as possible, within -//! the constraint of the maximum allowable frequency -//! alteration) the analyzed phases. -//! -//! \param partial The Partial whose frequencies, -//! and possibly phases (if the frequencies -//! cannot be sufficiently altered to match -//! the phases), will be recomputed. -//! \param maxFixPct The maximum allowable frequency -//! alteration, default is 0.2%. -// -void fixFrequency( Partial & partial, double maxFixPct = 0.2 ); - -// fixFrequency -// -//! Adjust frequencies of the Breakpoints in the -//! specified Partials such that the rendered Partial -//! achieves (or matches as nearly as possible, within -//! the constraint of the maximum allowable frequency -//! alteration) the analyzed phases. -//! -//! \param b The beginning of a range of Partials whose -//! frequencies should be fixed. -//! \param e The end of a range of Partials whose frequencies -//! should be fixed. -//! \param maxFixPct The maximum allowable frequency -//! alteration, default is 0.2%. -// -template < class Iter > -void fixFrequency( Iter b, Iter e, double maxFixPct = 0.2 ) -{ - while ( b != e ) - { - fixFrequency( *b, maxFixPct ); - ++b; - } -} - -// --------------------- useful phase maintenance utilities --------------------- - -// matchPhaseFwd -// -//! Compute the target frequency that will affect the -//! predicted (by the Breakpoint phases) amount of -//! sinusoidal phase travel between two breakpoints, -//! and assign that frequency to the target Breakpoint. -//! After computing the new frequency, update the phase of -//! the later Breakpoint. -//! -//! The most common kinds of errors are local (or burst) errors in -//! frequency and phase. These errors are best corrected by correcting -//! less than half the detected error at any time. Correcting more -//! than that will produce frequency oscillations for the remainder of -//! the Partial, in the case of a single bad frequency (as is common -//! at the onset of a tone). Any damping factor less then one will -//! converge eventually, .5 or less will converge without oscillating. -//! Use the damping argument to control the damping of the correction. -//! Specify 1 for no damping. -//! -//! -//! \pre The two Breakpoints are assumed to be consecutive in -//! a Partial. -//! \param bp0 The earlier Breakpoint. -//! \param bp1 The later Breakpoint. -//! \param dt The time (in seconds) between bp0 and bp1. -//! \param damping The fraction of the amount of phase error that will -//! be corrected (.5 or less will prevent frequency oscilation -//! due to burst errors in phase). -//! \param maxFixPct The maximum amount of frequency adjustment -//! that can be made to the frequency of bp1, expressed -//! as a precentage of the unmodified frequency of bp1. -//! If the necessary amount of frequency adjustment exceeds -//! this amount, then the phase will not be matched, -//! but will be updated as well to be consistent with -//! the frequencies. (default is 0.2%) -// -void matchPhaseFwd( Breakpoint & bp0, Breakpoint & bp1, - double dt, double damping, double maxFixPct = 0.2 ); - -// phaseTravel -// -//! Compute the sinusoidal phase travel between two Breakpoints. -//! Return the total unwrapped phase travel. -//! -//! \pre The two Breakpoints are assumed to be consecutive in -//! a Partial. -//! \param bp0 The earlier Breakpoint. -//! \param bp1 The later Breakpoint. -//! \param dt The time (in seconds) between bp0 and bp1. -//! \return The total unwrapped phase travel in radians. -// -double phaseTravel( const Breakpoint & bp0, const Breakpoint & bp1, double dt ); - -// wrapPi -// -//! Wrap an unwrapped phase value to the range (-pi,pi]. -//! -//! \param x The unwrapped phase in radians. -//! \return The phase (in radians) wrapped to the range (-Pi,Pi]. -// -double wrapPi( double x ); - - -} // end of namespace Loris - -#endif // ndef PHASEFIX_H - diff --git a/loris_library/loris_library.jucer b/loris_library/loris_library.jucer deleted file mode 100644 index 76aee81..0000000 --- a/loris_library/loris_library.jucer +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -