Skip to content

Commit

Permalink
- library update: added create_envelope, create_snapshot, loris_prepare
Browse files Browse the repository at this point in the history
  • Loading branch information
Christoph Hart committed May 28, 2023
1 parent 4d35fd9 commit aaf594f
Show file tree
Hide file tree
Showing 11 changed files with 569 additions and 142 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ loris_library_win64.zip
tmpFile
Loris Toolbox/Binaries/Builds
Loris Toolbox/Binaries
loris_library/docs/html
8 changes: 3 additions & 5 deletions loris_library/Source/Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ void Options::initLorisParameters()
hoptime = analyzer_getHopTime();
croptime = analyzer_getCropTime();
freqfloor = analyzer_getFreqFloor();
freqdrift = analyzer_getFreqDrift();
ampfloor = analyzer_getAmpFloor();
sidelobes = analyzer_getSidelobeLevel();
bwregionwidth = analyzer_getBwRegionWidth();
Expand All @@ -81,12 +80,11 @@ bool Options::update(const juce::Identifier& id, const juce::var& value)
return true;
}

return true;

if (id == OptionIds::freqfloor) { freqfloor = (double)value; analyzer_setFreqFloor(freqfloor); return true; }
if (id == OptionIds::ampfloor) { ampfloor = (double)value; analyzer_setAmpFloor(ampfloor); return true; }
if (id == OptionIds::sidelobes) { sidelobes = (double)value; analyzer_setSidelobeLevel(sidelobes); return true; }
if (id == OptionIds::freqdrift) { freqdrift = (double)value; analyzer_setFreqDrift(freqdrift); return true; }
if (id == OptionIds::freqdrift) { freqdrift = (double)value;
return true; }
if (id == OptionIds::hoptime) { hoptime = (double)value; analyzer_setHopTime(hoptime); return true; }
if (id == OptionIds::croptime) { croptime = (double)value; analyzer_setCropTime(croptime); return true; }
if (id == OptionIds::bwregionwidth) { bwregionwidth = (double)value; analyzer_setBwRegionWidth(bwregionwidth); return true; }
Expand All @@ -109,4 +107,4 @@ void Helpers::logMessage(const char* msg)
LorisState::getCurrentInstance()->messages.add(juce::String(msg));
}

}
}
162 changes: 99 additions & 63 deletions loris_library/Source/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,93 +38,129 @@ enum class TimeDomainType
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;
double freqfloor;

/** 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;
double freqdrift;

/** 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;
};

struct Helpers
/** This struct will be used as argument for the custom function. */
struct CustomFunctionArgs
{
struct FunctionPOD
{
// Constants
int channelIndex = 0;
int partialIndex = 0;
double sampleRate = 44100.0;
double rootFrequency = 0.0;
void* obj = nullptr;

// Variable properties
double time = 0.0;
double frequency = 0.0;
double phase = 0.0;
double gain = 1.0;
double bandwidth = 0.0;

};

struct CustomFunctionArgs
{
CustomFunctionArgs(void* obj_, const Breakpoint& b, int channelIndex_,
int partialIndex_,
double sampleRate_,
double time_,
double rootFrequency_) :
channelIndex(channelIndex_),
partialIndex(partialIndex_),
sampleRate(sampleRate_),
rootFrequency(rootFrequency_),
obj(obj_),
time(time_)
{
static_assert(sizeof(CustomFunctionArgs) == sizeof(FunctionPOD), "not the same size");

frequency = b.frequency();
phase = b.phase();
gain = b.amplitude();
bandwidth = b.bandwidth();
};

// Constants
const int channelIndex = 0;
const int partialIndex = 0;
const double sampleRate = 44100.0;
const double rootFrequency = 0.0;
void* obj = nullptr;

// Variable properties
double time = 0.0;
double frequency = 0.0;
double phase = 0.0;
double gain = 1.0;
double bandwidth = 0.0;


};

using CustomFunctionType = bool(*)(CustomFunctionArgs&);
using CustomFunction = std::function<bool(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<bool(CustomFunctionArgs&)>;
/** 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);
};

}
}
31 changes: 28 additions & 3 deletions loris_library/Source/LorisState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,16 @@ void LorisState::resetState(void* 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)
{
Expand Down Expand Up @@ -78,9 +87,11 @@ bool LorisState::analyse(const juce::File& audioFile, double rootFrequency)
juce::AudioFormatManager m;
m.registerBasicFormats();

auto driftFactor = std::pow(2.0, currentOption.freqdrift / 1200.0);

analyzer_configure(rootFrequency * 0.8, rootFrequency);
//analyzer_setWindowWidth(rootFrequency * currentOption.windowwidth);
analyzer_setFreqDrift(0.2 * rootFrequency);
analyzer_setFreqDrift(rootFrequency * 0.25);

currentOption.initLorisParameters();

Expand Down Expand Up @@ -115,7 +126,8 @@ bool LorisState::analyse(const juce::File& audioFile, double rootFrequency)
}

newEntry->saveAsOriginal();

newEntry->prepareToMorph();

analysedFiles.add(newEntry);

messages.add("... Analysed OK");
Expand All @@ -125,6 +137,16 @@ bool LorisState::analyse(const juce::File& audioFile, double rootFrequency)
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;
Expand Down Expand Up @@ -154,4 +176,7 @@ bool LorisState::setOption(const juce::Identifier& id, const juce::var& data)
return true;
}

}



}
69 changes: 45 additions & 24 deletions loris_library/Source/LorisState.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "Helpers.h"
#include "MultichannelPartialList.h"

#include <JuceHeader.h>
#include "JuceHeader.h"

namespace loris2hise {
using namespace juce;
Expand All @@ -34,35 +34,56 @@ using namespace juce;
*/
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);

Options currentOption;

juce::Result lastError;
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 {};
}

private:

juce::OwnedArray<MultichannelPartialList> analysedFiles;
friend class Helpers;

Options currentOption;

juce::StringArray messages;
juce::Result lastError;

private:
juce::OwnedArray<MultichannelPartialList> analysedFiles;

juce::StringArray messages;

static LorisState* currentInstance;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LorisState);
};

}
}
Loading

0 comments on commit aaf594f

Please sign in to comment.