Move dead submodules in-tree

Signed-off-by: swurl <swurl@swurl.xyz>
This commit is contained in:
swurl 2025-05-31 02:33:02 -04:00
parent c0cceff365
commit 6c655321e6
No known key found for this signature in database
GPG key ID: A5A7629F109C8FD1
4081 changed files with 1185566 additions and 45 deletions

View file

@ -0,0 +1,80 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_DUPLEXCALLBACK_H
#define ANDROID_FXLAB_DUPLEXCALLBACK_H
#include <oboe/Oboe.h>
// This callback handles mono in, stereo out synchronized audio passthrough.
// It takes a function which operates on two pointers (beginning and end)
// of underlying data.
template<class numeric_type>
class DuplexCallback : public oboe::AudioStreamCallback {
public:
DuplexCallback(oboe::AudioStream &inStream,
std::function<void(numeric_type *, numeric_type *)> fun,
size_t buffer_size, std::function<void(void)> restartFunction) :
kBufferSize(buffer_size), inRef(inStream), f(fun), restart(restartFunction) {}
oboe::DataCallbackResult
onAudioReady(oboe::AudioStream *outputStream, void *audioData, int32_t numFrames) override {
auto *outputData = static_cast<numeric_type *>(audioData);
auto outputChannelCount = outputStream->getChannelCount();
// Silence first to simplify glitch detection
std::fill(outputData, outputData + numFrames * outputChannelCount, 0);
oboe::ResultWithValue<int32_t> result = inRef.read(inputBuffer.get(), numFrames, 0);
int32_t framesRead = result.value();
if (!result) {
inRef.requestStop();
return oboe::DataCallbackResult::Stop;
}
if (mSpinUpCallbacks > 0 && framesRead > 0) {
mSpinUpCallbacks--;
return oboe::DataCallbackResult::Continue;
}
f(inputBuffer.get(), inputBuffer.get() + framesRead);
for (int i = 0; i < framesRead; i++) {
for (size_t j = 0; j < outputChannelCount; j++) {
*outputData++ = inputBuffer[i];
}
}
return oboe::DataCallbackResult::Continue;
}
void onErrorAfterClose(oboe::AudioStream *, oboe::Result result) override {
inRef.close();
if (result == oboe::Result::ErrorDisconnected) {
restart();
}
}
private:
int mSpinUpCallbacks = 10; // We will let the streams sync for the first few valid frames
const size_t kBufferSize;
oboe::AudioStream &inRef;
std::function<void(numeric_type *, numeric_type *)> f;
std::function<void(void)> restart;
std::unique_ptr<numeric_type[]> inputBuffer = std::make_unique<numeric_type[]>(kBufferSize);
};
#endif //ANDROID_FXLAB_DUPLEXCALLBACK_H

View file

@ -0,0 +1,93 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DuplexEngine.h"
#include "effects/Effects.h"
DuplexEngine::DuplexEngine() {
beginStreams();
}
void DuplexEngine::beginStreams() {
// This ordering is extremely important
openInStream();
if (inStream->getFormat() == oboe::AudioFormat::Float) {
functionList.emplace<FunctionList<float *>>();
createCallback<float_t>();
} else if (inStream->getFormat() == oboe::AudioFormat::I16) {
createCallback<int16_t>();
} else {
stopStreams();
}
SAMPLE_RATE = inStream->getSampleRate();
openOutStream();
oboe::Result result = startStreams();
if (result != oboe::Result::OK) stopStreams();
}
template<class numeric>
void DuplexEngine::createCallback() {
mCallback = std::make_unique<DuplexCallback<numeric>>(
*inStream, [&functionStack = this->functionList](numeric *beg, numeric *end) {
std::get<FunctionList<numeric *>>(functionStack)(beg, end);
},
inStream->getBufferCapacityInFrames(),
std::bind(&DuplexEngine::beginStreams, this));
}
oboe::AudioStreamBuilder DuplexEngine::defaultBuilder() {
return *oboe::AudioStreamBuilder()
.setPerformanceMode(oboe::PerformanceMode::LowLatency)
->setSharingMode(oboe::SharingMode::Exclusive);
}
void DuplexEngine::openInStream() {
defaultBuilder().setDirection(oboe::Direction::Input)
->setFormat(oboe::AudioFormat::Float) // For now
->setChannelCount(1) // Mono in for effects processing
->openManagedStream(inStream);
}
void DuplexEngine::openOutStream() {
defaultBuilder().setCallback(mCallback.get())
->setSampleRate(inStream->getSampleRate())
->setFormat(inStream->getFormat())
->setChannelCount(2) // Stereo out
->openManagedStream(outStream);
}
oboe::Result DuplexEngine::startStreams() {
oboe::Result result = outStream->requestStart();
int64_t timeoutNanos = 500 * 1000000; // arbitrary 1/2 second
auto currentState = outStream->getState();
auto nextState = oboe::StreamState::Unknown;
while (result == oboe::Result::OK && currentState != oboe::StreamState::Started) {
result = outStream->waitForStateChange(currentState, &nextState, timeoutNanos);
currentState = nextState;
}
if (result != oboe::Result::OK) return result;
return inStream->requestStart();
}
oboe::Result DuplexEngine::stopStreams() {
oboe::Result outputResult = inStream->requestStop();
oboe::Result inputResult = outStream->requestStop();
if (outputResult != oboe::Result::OK) return outputResult;
return inputResult;
}

View file

@ -0,0 +1,64 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef EFFECTS_APP_DUPLEXSTREAM_H
#define EFFECTS_APP_DUPLEXSTREAM_H
#include <array>
#include <algorithm>
#include <variant>
#include <oboe/Oboe.h>
#include "FunctionList.h"
#include "DuplexCallback.h"
class DuplexEngine {
public:
DuplexEngine();
void beginStreams();
virtual ~DuplexEngine() = default;
oboe::Result startStreams();
oboe::Result stopStreams();
std::variant<FunctionList<int16_t *>, FunctionList<float *>> functionList{
std::in_place_type<FunctionList<int16_t *>>};
private:
void openInStream();
void openOutStream();
static oboe::AudioStreamBuilder defaultBuilder();
template<class numeric>
void createCallback();
oboe::ManagedStream inStream;
std::unique_ptr<oboe::AudioStreamCallback> mCallback;
oboe::ManagedStream outStream;
};
#endif //EFFECTS_APP_DUPLEXSTREAM_H

View file

@ -0,0 +1,85 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef ANDROID_FXLAB_FUNCTIONLIST_H
#define ANDROID_FXLAB_FUNCTIONLIST_H
#include <vector>
#include <functional>
#include <array>
template<class iter_type>
class FunctionList {
std::vector<std::pair<std::function<void(iter_type, iter_type)>, bool>> functionList;
bool muted = false;
public:
FunctionList() = default;
FunctionList(const FunctionList &) = delete;
FunctionList &operator=(const FunctionList &) = delete;
void operator()(iter_type begin, iter_type end) {
for (auto &f : functionList) {
if (f.second == true) std::get<0>(f)(begin, end);
}
if (muted) std::fill(begin, end, 0);
}
void addEffect(std::function<void(iter_type, iter_type)> f) {
functionList.emplace_back(std::move(f), true);
}
void removeEffectAt(unsigned int index) {
if (index < functionList.size()) {
functionList.erase(std::next(functionList.begin(), index));
}
}
void rotateEffectAt(unsigned int from, unsigned int to) {
auto &v = functionList;
if (from >= v.size() || to >= v.size()) return;
if (from <= to) {
std::rotate(v.begin() + from, v.begin() + from + 1, v.begin() + to + 1);
} else {
from = v.size() - 1 - from;
to = v.size() - 1 - to;
std::rotate(v.rbegin() + from, v.rbegin() + from + 1, v.rbegin() + to + 1);
}
}
void modifyEffectAt(size_t index, std::function<void(iter_type, iter_type)> fun) {
functionList[index] = {std::move(fun), functionList[index].second};
}
void enableEffectAt(size_t index, bool enable) {
functionList[index].second = enable;
}
void mute(bool toMute) {
muted = toMute;
}
auto getType() {
return iter_type();
}
};
#endif //ANDROID_FXLAB_FUNCTIONLIST_H

View file

@ -0,0 +1,53 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_COMBFILTER_H
#define ANDROID_FXLAB_COMBFILTER_H
#include "utils/DelayLine.h"
template <class iter_type>
class CombFilter {
public:
// delay > 0 in samples
CombFilter(float blend, float feedForward, float feedBack, int delay) :
kBlend(blend),
kFeedForward(feedForward),
kFeedBack(feedBack),
kDelay(static_cast<size_t>(delay)) {}
void operator () (typename std::iterator_traits<iter_type>::reference x) {
auto delayOutput = delayLine[kDelay];
auto delayInput = x + kFeedBack * delayOutput;
delayLine.push(delayInput);
x = delayInput * kBlend + delayOutput * kFeedForward;
}
void operator () (iter_type begin, iter_type end) {
for (; begin != end; ++begin) {
operator()(*begin);
}
}
private:
// Weights
const float kBlend;
const float kFeedForward;
const float kFeedBack;
const size_t kDelay;
DelayLine<typename std::iterator_traits<iter_type>::value_type> delayLine {kDelay + 1};
};
#endif //ANDROID_FXLAB_COMBFILTER_H

View file

@ -0,0 +1,79 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_DELAYLINEEFFECT_H
#define ANDROID_FXLAB_DELAYLINEEFFECT_H
#include <functional>
#include "utils/SineWave.h"
#include "utils/DelayLine.h"
// Abstract class for implementing delay line based effects
// This functor retains state (it must be used sequentially)
// Effects are float, mono, 48000 hz
template <class iter_type>
class DelayLineEffect {
public:
// delay > 0, depth in samples, mod is control signal
DelayLineEffect(float blend, float feedForward, float feedBack, int delay, int depth, std::function<float()> &&mod) :
kBlend(blend),
kFeedForward(feedForward),
kFeedBack(feedBack),
kDelay(delay),
kDepth(depth),
mMod(mod) { }
void operator () (typename std::iterator_traits<iter_type>::reference x) {
auto delayInput = x + kFeedBack * delayLine[kTap];
auto variableDelay = mMod() * kDepth + kTap;
int index = static_cast<int>(variableDelay);
auto fracComp = 1 - (variableDelay - index);
//linear
// auto interpolated = fracComp * delayLine[index] + (1 - fracComp) * delayLine[index + 1];
// all - pass
float interpolated = fracComp * delayLine[index] + delayLine[index + 1]
- fracComp * prevInterpolated;
prevInterpolated = interpolated;
delayLine.push(delayInput);
x = interpolated * kFeedForward + kBlend * delayInput;
}
void operator () (iter_type begin, iter_type end) {
for (; begin != end; ++begin) {
operator()(*begin);
}
}
private:
// Weights
const float kBlend;
const float kFeedForward;
const float kFeedBack;
const int kDelay;
const int kDepth;
const int kTap = kDelay + kDepth;
// Control function
const std::function<float()> mMod;
// Memory
float prevInterpolated = 0; // for all pass interp
const size_t kDelayLineSize = kTap + kDepth + 1; // index one is immediate prev sample
DelayLine<typename std::iterator_traits<iter_type>::value_type> delayLine {kDelayLineSize};
};
#endif //ANDROID_FXLAB_DELAYLINEEFFECT_H

View file

@ -0,0 +1,34 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_DOUBLINGEFFECT_H
#define ANDROID_FXLAB_DOUBLINGEFFECT_H
#include "DelayLineEffect.h"
#include "utils/WhiteNoise.h"
template <class iter_type>
class DoublingEffect: public DelayLineEffect<iter_type> {
public:
DoublingEffect(float depth_ms, float delay_ms, float noise_pass):
DelayLineEffect<iter_type> {0.7071, 0.7071, 0,
static_cast<int>(delay_ms * SAMPLE_RATE / 1000),
static_cast<int>(depth_ms * SAMPLE_RATE / 1000),
std::function<float()>{WhiteNoise{static_cast<int>(4800 * noise_pass)}}}
{}
};
#
#endif //ANDROID_FXLAB_DOUBLINGEFFECT_H

View file

@ -0,0 +1,41 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_DRIVECONTROL_H
#define ANDROID_FXLAB_DRIVECONTROL_H
#include <functional>
template <class iter_type>
class DriveControl {
public:
DriveControl(std::function<void(iter_type, iter_type)> function, double scale):
mFunction(function), kScale(scale) {}
void operator() (iter_type beg, iter_type end) {
std::for_each(beg, end, [this](auto &x){x *= kScale;});
mFunction(beg, end);
std::for_each(beg, end, [this](auto &x){x *= recip;});
}
private:
std::function<void(iter_type, iter_type)> mFunction;
const double kScale;
const double recip = 1 / kScale;
};
#endif //ANDROID_FXLAB_DRIVECONTROL_H

View file

@ -0,0 +1,33 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_ECHOEFFECT_H
#define ANDROID_FXLAB_ECHOEFFECT_H
#include "DelayLineEffect.h"
#include "utils/WhiteNoise.h"
template <class iter_type>
class EchoEffect: public DelayLineEffect<iter_type> {
public:
EchoEffect(float feedback, float delay_ms):
DelayLineEffect<iter_type> {1, 0, feedback,
static_cast<int>(delay_ms * SAMPLE_RATE / 1000),
0,
std::function<float()>{[](){return 0.0;}}}
{}
};
#endif //ANDROID_FXLAB_ECHOEFFECT_H

View file

@ -0,0 +1,61 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_EFFECTS_H
#define ANDROID_FXLAB_EFFECTS_H
// The Sample Rate for effects
static int SAMPLE_RATE = 48000;
// This header should include the various effect descriptions
#include "descrip/EffectDescription.h"
#include "descrip/PassthroughDescription.h"
#include "descrip/VibratoDescription.h"
#include "descrip/TremoloDescription.h"
#include "descrip/GainDescription.h"
#include "descrip/FlangerDescription.h"
#include "descrip/WhiteChorusDescription.h"
#include "descrip/FIRDescription.h"
#include "descrip/IIRDescription.h"
#include "descrip/AllPassDescription.h"
#include "descrip/DoublingDescription.h"
#include "descrip/OverdriveDescription.h"
#include "descrip/DistortionDescription.h"
#include "descrip/EchoDescription.h"
#include "descrip/SlapbackDescription.h"
constexpr std::tuple<
Effect::PassthroughDescription,
Effect::TremoloDescription,
Effect::VibratoDescription,
Effect::GainDescription,
Effect::FlangerDescription,
Effect::WhiteChorusDescription,
Effect::FIRDescription,
Effect::IIRDescription,
Effect::AllPassDescription,
Effect::DoublingDescription,
Effect::OverdriveDescription,
Effect::DistortionDescription,
Effect::EchoDescription,
Effect::SlapbackDescription
> EffectsTuple{};
constexpr size_t numEffects = std::tuple_size<decltype(EffectsTuple)>::value;
#endif //ANDROID_FXLAB_EFFECTS_H

View file

@ -0,0 +1,29 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_FLANGEREFFECT_H
#define ANDROID_FXLAB_FLANGEREFFECT_H
#include "DelayLineEffect.h"
template<class iter_type>
class FlangerEffect : public DelayLineEffect<iter_type> {
public:
// feedback should be 0.7071
FlangerEffect(float depth_ms, float frequency, float feedback):
DelayLineEffect<iter_type>(feedback, feedback, feedback, 0, depth_ms * SAMPLE_RATE / 1000,
SineWave {frequency, 1, SAMPLE_RATE}) { }
};
#endif //ANDROID_FXLAB_FLANGEREFFECT_H

View file

@ -0,0 +1,56 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_SINGLEFUNCTIONEFFECTS_H
#define ANDROID_FXLAB_SINGLEFUNCTIONEFFECTS_H
#include <list>
namespace SingleFunctionEffects {
template<class floating>
void _overdrive (floating &x) {
static constexpr double third = (1.0 / 3.0);
auto abs = std::abs(x);
if (abs <= third) {
x *= 2;
} else if (abs <= 2 * third) {
x = std::copysign((3 - (2 - 3 * abs) * (2 - 3 * abs)) * third, x);
} else {
x = std::copysign(1, x);
}
}
template <class iter_type>
void overdrive(iter_type beg, iter_type end) {
for (; beg != end; ++beg){
_overdrive(*beg);
}
}
template <class floating>
void _distortion (floating &x) {
x = std::copysign(-std::expm1(-std::abs(x)), x);
}
template <class iter_type>
void distortion(iter_type beg, iter_type end) {
for (; beg != end; ++beg) {
_distortion(*beg);
}
}
}
#endif //ANDROID_FXLAB_SINGLEFUNCTIONEFFECTS_H

View file

@ -0,0 +1,30 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_SLAPBACKEFFECT_H
#define ANDROID_FXLAB_SLAPBACKEFFECT_H
template <class iter_type>
class SlapbackEffect: public DelayLineEffect<iter_type> {
public:
SlapbackEffect(float feedforward, float delay_ms):
DelayLineEffect<iter_type> {1, feedforward, 0,
static_cast<int>(delay_ms * SAMPLE_RATE / 1000),
0,
std::function<float()>{[](){return 0.0;}}}
{}
};
#endif //ANDROID_FXLAB_SLAPBACKEFFECT_H

View file

@ -0,0 +1,43 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_TREMOLOEFFECT_H
#define ANDROID_FXLAB_TREMOLOEFFECT_H
#include "utils/SineWave.h"
class TremoloEffect {
public:
TremoloEffect(float frequency, float height):
kCenter(1 - height),
kSignal {SineWave{frequency, height, SAMPLE_RATE}} { }
template <class numeric_type>
void operator () (numeric_type &x) {
x = x * (kSignal() + kCenter);
}
template <class iter_type>
void operator () (iter_type begin, iter_type end) {
for (; begin != end; ++begin) {
operator()(*begin);
}
}
private:
const float kCenter;
std::function<float()> kSignal;
};
#endif //ANDROID_FXLAB_TREMOLOEFFECT_H

View file

@ -0,0 +1,27 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_VIBRATROEFFECT_H
#define ANDROID_FXLAB_VIBRATROEFFECT_H
#include "DelayLineEffect.h"
template <class iter_type>
class VibratoEffect : public DelayLineEffect<iter_type> {
public:
VibratoEffect(float depth_ms, float frequency):
DelayLineEffect<iter_type>(0, 1, 0, 1, depth_ms * SAMPLE_RATE / 1000,
SineWave {frequency, 1, SAMPLE_RATE}) { }
};
#endif //ANDROID_FXLAB_VIBRATROEFFECT_H

View file

@ -0,0 +1,32 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_WHITECHORUSEFFECT_H
#define ANDROID_FXLAB_WHITECHORUSEFFECT_H
#include "DelayLineEffect.h"
#include "utils/WhiteNoise.h"
template <class iter_type>
class WhiteChorusEffect : public DelayLineEffect<iter_type> {
public:
WhiteChorusEffect(float depth_ms, float delay_ms, float noise_pass):
DelayLineEffect<iter_type> {0.7071, 1, -0.7071f,
static_cast<int>(delay_ms * SAMPLE_RATE / 1000),
static_cast<int>(depth_ms * SAMPLE_RATE / 1000),
std::function<float()>{WhiteNoise{static_cast<int>(4800 * noise_pass)}}}
{}
};
#endif //ANDROID_FXLAB_WHITECHORUSEFFECT_H

View file

@ -0,0 +1,48 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_ALLPASSDESCRIPTION_H
#define ANDROID_FXLAB_ALLPASSDESCRIPTION_H
#include "EffectDescription.h"
#include "../CombFilter.h"
namespace Effect {
class AllPassDescription: public EffectDescription<AllPassDescription, 2> {
public:
static constexpr std::string_view getName() {
return std::string_view("AllPass");
}
static constexpr std::string_view getCategory() {
return std::string_view("Comb");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()> {
ParamType("Delay (samples)", 1, 500, 10),
ParamType("Scale", 0.01, 0.99, 0.5),
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
return _ef<iter_type> {
CombFilter<iter_type>{paramArr[1], 1, -(paramArr[1]), static_cast<int>(paramArr[0])}
};
}
};
} //namespace Effect
#endif //ANDROID_FXLAB_ALLPASSDESCRIPTION_H

View file

@ -0,0 +1,46 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_DISTORTIONDESCRIPTION_H
#define ANDROID_FXLAB_DISTORTIONDESCRIPTION_H
#include "EffectDescription.h"
#include "../SingleFunctionEffects.h"
namespace Effect {
class DistortionDescription: public EffectDescription<DistortionDescription, 1> {
public:
static constexpr std::string_view getName() {
return std::string_view("Distortion");
}
static constexpr std::string_view getCategory() {
return std::string_view("Nonlinear");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()> {
ParamType("Drive (db)", -10, 50, 0)
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
double scale = pow(2.0, paramArr[0] / 10);
return DriveControl<iter_type> {SingleFunctionEffects::distortion<iter_type>, scale};
}
};
}
#endif //ANDROID_FXLAB_DISTORTIONDESCRIPTION_H

View file

@ -0,0 +1,33 @@
#ifndef ANDROID_FXLAB_DOUBLINGDESCRIPTION_H
#define ANDROID_FXLAB_DOUBLINGDESCRIPTION_H
#include "EffectDescription.h"
#include "../DoublingEffect.h"
namespace Effect {
class DoublingDescription: public EffectDescription<DoublingDescription, 3> {
public:
static constexpr std::string_view getName() {
return std::string_view("Doubling");
}
static constexpr std::string_view getCategory() {
return std::string_view("Delay");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()> {
ParamType("Depth (ms)", 10, 100, 40),
ParamType("Delay (ms)", 1, 100, 40),
ParamType("Noise pass", 1, 10, 4),
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
return _ef<iter_type> {
DoublingEffect<iter_type>{paramArr[0], paramArr[1], paramArr[2]}
};
}
};
} //namespace Effect
#endif //ANDROID_FXLAB_DOUBLINGDESCRIPTION_H

View file

@ -0,0 +1,48 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_ECHODESCRIPTION_H
#define ANDROID_FXLAB_ECHODESCRIPTION_H
#include "../EchoEffect.h"
namespace Effect {
class EchoDescription: public EffectDescription<EchoDescription, 2> {
public:
static constexpr std::string_view getName() {
return std::string_view("Echo");
}
static constexpr std::string_view getCategory() {
return std::string_view("Delay");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()> {
ParamType("Feedback", 0, 1, 0.5),
ParamType("Delay (ms)", 50, 500, 100),
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
return _ef<iter_type> {
EchoEffect<iter_type>{paramArr[0], paramArr[1]}
};
}
};
} //namespace Effect
#endif //ANDROID_FXLAB_ECHODESCRIPTION_H

View file

@ -0,0 +1,107 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_EFFECTDESCRIPTION_H
#define ANDROID_FXLAB_EFFECTDESCRIPTION_H
#include <functional>
#include <array>
#include <vector>
#include <string_view>
template<class iter_type>
using _ef = std::function<void(iter_type, iter_type)>;
// Only Effect Descriptions should use this namespace
namespace Effect {
class ParamType {
public:
constexpr ParamType(std::string_view name, float minVal, float maxVal, float defVal) :
kName(name),
kMinVal(minVal),
kMaxVal(maxVal),
kDefVal(defVal) {}
constexpr ParamType(const ParamType &other) = delete;
ParamType &operator=(const ParamType &other) = delete;
constexpr ParamType(ParamType &&other) = default;
constexpr ParamType &operator=(ParamType &&other) = delete;
const std::string_view kName;
const float kMinVal, kMaxVal, kDefVal;
};
// EffectType is the description subclass, N is num of params
// Function implementations in this class contain shared behavior
// Which can be shadowed.
template<class EffectType, size_t N>
class EffectDescription {
public:
// These methods will be shadowed by subclasses
static constexpr size_t getNumParams() {
return N;
}
static constexpr std::array<float, N> getEmptyParams() {
return std::array<float, EffectType::getNumParams()>();
}
static constexpr std::string_view getName();
static constexpr std::string_view getCategory();
static constexpr std::array<ParamType, N> getParams();
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, N> paramArr);
template<class iter_type>
static _ef<iter_type> buildDefaultEffect() {
auto params = EffectType::getEmptyParams();
int i = 0;
for (ParamType &mParam: EffectType::getParams()) {
params[i++] = mParam.kDefVal;
}
return EffectType::template buildEffect<iter_type>(params);
}
// The default behavior is new effect, can be shadowed
template<class iter_type>
static _ef<iter_type> modifyEffect(
_ef<iter_type> /* effect */, std::array<float, N> paramArr) {
return EffectType::template buildEffect<iter_type>(std::move(paramArr));
}
template <class iter_type>
static _ef<iter_type> modifyEffectVec(
_ef<iter_type> effect, std::vector<float> paramVec) {
std::array<float, N> arr;
std::copy_n(paramVec.begin(), N, arr.begin());
return EffectType::template modifyEffect<iter_type>(
std::move(effect), std::move(arr));
}
};
} // namespace effect
#endif //ANDROID_FXLAB_EFFECTDESCRIPTION_H

View file

@ -0,0 +1,46 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_FIRDESCRIPTION_H
#define ANDROID_FXLAB_FIRDESCRIPTION_H
#include "EffectDescription.h"
#include "../CombFilter.h"
namespace Effect {
class FIRDescription: public EffectDescription<FIRDescription, 2> {
public:
static constexpr std::string_view getName() {
return std::string_view("FIR");
}
static constexpr std::string_view getCategory() {
return std::string_view("Comb");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()> {
ParamType("Delay (samples)", 1, 500, 10),
ParamType("Gain", 0, 0.99, 0.5),
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
return _ef<iter_type> {
CombFilter<iter_type>{1, paramArr[1], 0, static_cast<int>(paramArr[0])}
};
}
};
} //namespace Effect
#endif //ANDROID_FXLAB_FIRDESCRIPTION_H

View file

@ -0,0 +1,50 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_FLANGERDESCRIPTION_H
#define ANDROID_FXLAB_FLANGERDESCRIPTION_H
#include "EffectDescription.h"
#include "../FlangerEffect.h"
namespace Effect {
class FlangerDescription : public EffectDescription<FlangerDescription, 3> {
public:
static constexpr std::string_view getName() {
return std::string_view("Flanger");
}
static constexpr std::string_view getCategory() {
return std::string_view("Delay");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, 3> {
ParamType("Depth (ms)", 0.1, 2, 1),
ParamType("Frequency", 0.1, 1, 0.2),
ParamType("Feedback", 0, 0.95, 0.7071),
};
}
template <class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
return std::function<void(iter_type, iter_type)> {
FlangerEffect<iter_type>{paramArr[0], paramArr[1], paramArr[2]}
};
}
};
} // namespace Effect
#endif //ANDROID_FXLAB_FLANGERDESCRIPTION_H

View file

@ -0,0 +1,50 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_GAINDESCRIPTION_H
#define ANDROID_FXLAB_GAINDESCRIPTION_H
#include "EffectDescription.h"
#include <cmath>
#include <iostream>
namespace Effect {
class GainDescription : public EffectDescription<GainDescription, 1> {
public:
static constexpr std::string_view getName() {
return std::string_view("Gain");
}
static constexpr std::string_view getCategory() {
return std::string_view("None");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array <ParamType, getNumParams()> {
ParamType("Gain", -30, 20, 0)
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
float scale = paramArr[0] / 10;
return _ef<iter_type> {
[=](iter_type beg, iter_type end) {
for (; beg != end; ++beg) *beg *= pow(2.0, scale);
}
};
}
};
} // namespace Effect
#endif //ANDROID_FXLAB_GAINDESCRIPTION_H

View file

@ -0,0 +1,50 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_IIRDESCRIPTION_H
#define ANDROID_FXLAB_IIRDESCRIPTION_H
#include "../CombFilter.h"
namespace Effect {
class IIRDescription: public EffectDescription<IIRDescription, 3> {
public:
static constexpr std::string_view getName() {
return std::string_view("IIR");
}
static constexpr std::string_view getCategory() {
return std::string_view("Comb");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()> {
ParamType("Delay (samples)", 1, 500, 10),
ParamType("Gain", 0, 0.99, 0.5),
ParamType("Scale", 0.25, 0.99, 0.5)
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
return _ef<iter_type> {
CombFilter<iter_type>{paramArr[2], 0, paramArr[1], static_cast<int>(paramArr[0])}
};
}
};
} //namespace Effect
#
#endif //ANDROID_FXLAB_IIRDESCRIPTION_H

View file

@ -0,0 +1,51 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_OVERDRIVEDESCRIPTION_H
#define ANDROID_FXLAB_OVERDRIVEDESCRIPTION_H
#include <limits>
#include <cmath>
#include <iterator>
#include "EffectDescription.h"
#include "../SingleFunctionEffects.h"
#include "../DriveControl.h"
namespace Effect {
class OverdriveDescription : public EffectDescription<OverdriveDescription, 1> {
public:
static constexpr std::string_view getName() {
return std::string_view("Overdrive");
}
static constexpr std::string_view getCategory() {
return std::string_view("Nonlinear");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()>{
ParamType("Drive (db)", -10, 50, 0)
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
double scale = pow(2.0, paramArr[0] / 10);
return DriveControl<iter_type> {SingleFunctionEffects::overdrive<iter_type>, scale};
}
};
}
#endif //ANDROID_FXLAB_OVERDRIVEDESCRIPTION_H

View file

@ -0,0 +1,48 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_PASSTHROUGHDESCRIPTION_H
#define ANDROID_FXLAB_PASSTHROUGHDESCRIPTION_H
#include "EffectDescription.h"
namespace Effect {
class PassthroughDescription : public EffectDescription<PassthroughDescription, 0> {
public:
static constexpr std::string_view getName() {
return std::string_view("Passthrough");
}
static constexpr std::string_view getCategory() {
return std::string_view("None");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, 0>();
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> ) {
return [](iter_type, iter_type) {};
}
};
} // namespace Effect
#endif //ANDROID_FXLAB_PASSTHROUGHDESCRIPTION_H

View file

@ -0,0 +1,50 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_SLAPBACKDESCRIPTION_H
#define ANDROID_FXLAB_SLAPBACKDESCRIPTION_H
#include "EffectDescription.h"
#include "../SlapbackEffect.h"
namespace Effect {
class SlapbackDescription: public EffectDescription<SlapbackDescription, 2> {
public:
static constexpr std::string_view getName() {
return std::string_view("Slapback");
}
static constexpr std::string_view getCategory() {
return std::string_view("Delay");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()> {
ParamType("Feedforward", 0, 2, 0.5),
ParamType("Delay (ms)", 30, 100, 50),
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
return _ef<iter_type> {
SlapbackEffect<iter_type>{paramArr[0], paramArr[1]}
};
}
};
} //namespace Effect
#endif //ANDROID_FXLAB_SLAPBACKDESCRIPTION_H

View file

@ -0,0 +1,46 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_TREMOLODESCRIPTION_H
#define ANDROID_FXLAB_TREMOLODESCRIPTION_H
#include "EffectDescription.h"
#include "../TremoloEffect.h"
namespace Effect {
class TremoloDescription : public EffectDescription<TremoloDescription, 2> {
public:
static constexpr std::string_view getName() {
return std::string_view("Tremolo");
}
static constexpr std::string_view getCategory() {
return std::string_view("None");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()> {
ParamType("Frequency", 0.1, 5.0, 2),
ParamType("Height", 0.05, 0.45, 0.25)
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr ) {
return _ef<iter_type> {
TremoloEffect {paramArr[0], paramArr[1]}};
}
};
} // namespace Effect
#endif // ANDROID_FXLAB_TREMOLODESCRIPTION_H

View file

@ -0,0 +1,47 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_VIBRATODESCRIPTION_H
#define ANDROID_FXLAB_VIBRATODESCRIPTION_H
#include "EffectDescription.h"
#include "../VibratroEffect.h"
namespace Effect {
class VibratoDescription : public EffectDescription<VibratoDescription, 2> {
public:
static constexpr std::string_view getName() {
return std::string_view("Vibrato");
}
static constexpr std::string_view getCategory() {
return std::string_view("Delay");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()> {
ParamType("Depth (ms)", 0, 3, 1),
ParamType("Frequency", 0.1, 5, 1)
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
return _ef<iter_type> {
VibratoEffect<iter_type>{paramArr[0], paramArr[1]}
};
}
};
} //namespace Effect
#endif //ANDROID_FXLAB_VIBRATODESCRIPTION_H

View file

@ -0,0 +1,49 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_WHITECHORUSDESCRIPTION_H
#define ANDROID_FXLAB_WHITECHORUSDESCRIPTION_H
#include "EffectDescription.h"
#include "../WhiteChorusEffect.h"
namespace Effect {
class WhiteChorusDescription : public EffectDescription<WhiteChorusDescription, 3> {
public:
static constexpr std::string_view getName() {
return std::string_view("White Chorus");
}
static constexpr std::string_view getCategory() {
return std::string_view("Delay");
}
static constexpr std::array<ParamType, getNumParams()> getParams() {
return std::array<ParamType, getNumParams()> {
ParamType("Depth (ms)", 1, 30, 10),
ParamType("Delay (ms)", 1, 30, 10),
ParamType("Noise pass", 1, 10, 4),
};
}
template<class iter_type>
static _ef<iter_type> buildEffect(std::array<float, getNumParams()> paramArr) {
return _ef<iter_type> {
WhiteChorusEffect<iter_type>{paramArr[0], paramArr[1], paramArr[2]}
};
}
};
} //namespace Effect
#endif //ANDROID_FXLAB_WHITECHORUSDESCRIPTION_H

View file

@ -0,0 +1,44 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_DELAYLINE_H
#define ANDROID_FXLAB_DELAYLINE_H
#include <vector>
template<class T>
class DelayLine {
public:
DelayLine(std::size_t size): N(size), mArr(N, 0) { }
void push(const T& value) {
mArr[mfront++] = value;
if (mfront == N) mfront = 0;
}
// indexed from last value written backwards
// i.e T-1 to T-N
const T& operator[](int i) {
int index = mfront - i;
if (index < 0) index += N;
return mArr[index];
}
private:
const int N;
int mfront = 0;
std::vector<T> mArr;
};
#endif //ANDROID_FXLAB_DELAYLINE_H

View file

@ -0,0 +1,41 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_PHASEACCUMULATOR_H
#define ANDROID_FXLAB_PHASEACCUMULATOR_H
#include <cmath>
class PhaseAccumulator {
public:
PhaseAccumulator(float frequency, float sampleRate):
f(frequency),
fs(sampleRate) { }
float incrementPhase() {
mPhase += kDelta;
if (mPhase >= kTwoPi) mPhase -= kTwoPi;
return mPhase;
}
private:
float mPhase = 0;
const float f;
const float fs;
static constexpr float kTwoPi = M_PI * 2;
const float kDelta = kTwoPi * f / fs;
};
#endif //ANDROID_FXLAB_PHASEACCUMULATOR_H

View file

@ -0,0 +1,37 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_SINEWAVE_H
#define ANDROID_FXLAB_SINEWAVE_H
#include "PhaseAccumulator.h"
class SineWave {
public:
// freq in hz
SineWave(float frequency, float amplitude, int sampleRate):
mPhasor(frequency, sampleRate),
kAmplitude(amplitude) { }
float operator() () {
return kAmplitude * sinf(mPhasor.incrementPhase());
}
private:
PhaseAccumulator mPhasor;
const float kAmplitude;
};
#endif //ANDROID_FXLAB_SINEWAVE_H

View file

@ -0,0 +1,36 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_WHITENOISE_H
#define ANDROID_FXLAB_WHITENOISE_H
class WhiteNoise {
const int kScale;
public:
WhiteNoise(int scale): kScale(scale) {}
float operator() () {
static int counter = 0;
static float r_0, r_1 = 0;
if (counter == 0) {
r_0 = r_1;
r_1 = (static_cast <float> (rand()) / static_cast <float> (RAND_MAX)) * 2 - 1;
}
float ret = r_0 + counter * (r_1 - r_0) / kScale;
if (++counter == kScale) counter = 0;
if (ret > 0.99) return 0.99f;
if (ret < -0.99) return -0.99f;
return ret;
}
};
#endif //ANDROID_FXLAB_WHITENOISE_H

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef __SAMPLE_ANDROID_DEBUG_H__
#define __SAMPLE_ANDROID_DEBUG_H__
#include <android/log.h>
#if 1
#ifndef MODULE_NAME
#define MODULE_NAME "AUDIO-APP"
#endif
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, MODULE_NAME, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, MODULE_NAME, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,MODULE_NAME, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,MODULE_NAME, __VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,MODULE_NAME, __VA_ARGS__)
#define ASSERT(cond, ...) if (!(cond)) {__android_log_assert(#cond, MODULE_NAME, __VA_ARGS__);}
#else
#define LOGV(...)
#define LOGD(...)
#define LOGI(...)
#define LOGW(...)
#define LOGE(...)
#define LOGF(...)
#define ASSERT(cond, ...)
#endif
#endif // __SAMPLE_ANDROID_DEBUG_H__

View file

@ -0,0 +1,160 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <cassert>
#include <string>
#include <functional>
#include <utility>
#include <vector>
#include "DuplexEngine.h"
#include "effects/Effects.h"
#include "FunctionList.h"
// JNI Utility functions and globals
static DuplexEngine *enginePtr = nullptr;
// Actual JNI interface
extern "C" {
JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_createAudioEngine(
JNIEnv,
jobject /* this */) {
enginePtr = new DuplexEngine();
}
JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_destroyAudioEngine(
JNIEnv,
jobject /* this */) {
if (!enginePtr) return;
delete enginePtr;
enginePtr = nullptr;
}
JNIEXPORT jobjectArray JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_getEffects(JNIEnv *env, jobject) {
jclass jcl = env->FindClass("com/mobileer/androidfxlab/datatype/EffectDescription");
jclass jparamcl = env->FindClass("com/mobileer/androidfxlab/datatype/ParamDescription");
assert (jcl != nullptr && jparamcl != nullptr);
auto jparamMethodId = env->GetMethodID(jparamcl, "<init>", "(Ljava/lang/String;FFF)V");
auto jMethodId = env->GetMethodID(jcl, "<init>",
"(Ljava/lang/String;Ljava/lang/String;I[Lcom/mobileer/androidfxlab/datatype/ParamDescription;)V");
auto arr = env->NewObjectArray(numEffects, jcl, nullptr);
auto lambda = [&](auto &arg, int i) {
const auto &paramArr = arg.getParams();
auto jparamArr = env->NewObjectArray(paramArr.size(), jparamcl, nullptr);
int c = 0;
for (auto const &elem: paramArr) {
jobject j = env->NewObject(jparamcl, jparamMethodId,
env->NewStringUTF(std::string(elem.kName).c_str()),
elem.kMinVal, elem.kMaxVal, elem.kDefVal);
assert(j != nullptr);
env->SetObjectArrayElement(jparamArr, c++, j);
}
jobject j = env->NewObject(jcl, jMethodId,
env->NewStringUTF(std::string(arg.getName()).c_str()),
env->NewStringUTF(std::string(arg.getCategory()).c_str()),
i, jparamArr);
assert(j != nullptr);
env->SetObjectArrayElement(arr, i, j);
};
int i = 0;
std::apply([&i, &lambda](auto &&... args) mutable { ((lambda(args, i++)), ...); },
EffectsTuple);
return arr;
}
JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_addDefaultEffectNative(JNIEnv *, jobject, jint jid) {
if (!enginePtr) return;
auto id = static_cast<int>(jid);
std::visit([id](auto &&stack) {
std::function<void(decltype(stack.getType()), decltype(stack.getType()))> f;
int i = 0;
std::apply([id, &f, &i](auto &&... args) mutable {
((f = (i++ == id) ?
args.template buildDefaultEffect<decltype(stack.getType())>() : f), ...);
}, EffectsTuple);
stack.addEffect(std::move(f));
}, enginePtr->functionList);
}
JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_removeEffectNative(JNIEnv *, jobject, jint jind) {
if (!enginePtr) return;
auto ind = static_cast<size_t>(jind);
std::visit([ind](auto &&arg) {
arg.removeEffectAt(ind);
}, enginePtr->functionList);
}
JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_rotateEffectNative(JNIEnv *, jobject,
jint jfrom, jint jto) {
if (!enginePtr) return;
auto from = static_cast<size_t>(jfrom);
auto to = static_cast<size_t>(jto);
std::visit([from, to](auto &&arg) {
arg.rotateEffectAt(from, to);
}, enginePtr->functionList);
}
JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_modifyEffectNative(
JNIEnv *env, jobject, jint jid, jint jindex, jfloatArray params) {
if (!enginePtr) return;
int id = static_cast<int>(jid);
int index = static_cast<size_t>(jindex);
jfloat *data = env->GetFloatArrayElements(params, nullptr);
std::vector<float> arr{data, data + env->GetArrayLength(params)};
env->ReleaseFloatArrayElements(params, data, 0);
std::visit([&arr, &id, &index](auto &&stack) {
std::function<void(decltype(stack.getType()), decltype(stack.getType()))> ef;
int i = 0;
std::apply([&](auto &&... args) mutable {
((ef = (i++ == id) ?
args.modifyEffectVec(ef, arr) : ef), ...);
}, EffectsTuple);
stack.modifyEffectAt(index, std::move(ef));
}, enginePtr->functionList);
}
JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_enableEffectNative(
JNIEnv *, jobject, jint jindex, jboolean jenable) {
if (!enginePtr) return;
auto ind = static_cast<size_t>(jindex);
auto enable = static_cast<bool>(jenable);
std::visit([ind, enable](auto &&args) {
args.enableEffectAt(ind, enable);
}, enginePtr->functionList);
}
JNIEXPORT void JNICALL
Java_com_mobileer_androidfxlab_NativeInterface_enablePassthroughNative(
JNIEnv *, jobject, jboolean jenable) {
if (!enginePtr) return;
std::visit([enable = static_cast<bool>(jenable)](auto &&args) {
args.mute(!enable);
}, enginePtr->functionList);
}
} //extern C

View file

@ -0,0 +1,5 @@
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
Makefile
runTests

View file

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.4.1)
project(Effects_Tests)
# We need C++17 to test
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Locate GTest
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
# Link runTests with what we want to test and the GTest and pthread library
add_executable(runTests testEffects.cpp)
target_link_libraries(runTests ${GTEST_LIBRARIES} pthread)

View file

@ -0,0 +1,52 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_DELAYLINEEFFECTTEST_H
#define ANDROID_FXLAB_DELAYLINEEFFECTTEST_H
#include <gtest/gtest.h>
#include "../effects/DelayLineEffect.h"
namespace {
TEST(DelayLineEffectTest, SingleFeedForwardTest) {
DelayLineEffect<float*> e1 {0, 1, 0, 1, 0, [](){return 0;}};
std::array<float, 5> inputData {1, 0, 0.5, 0.25, 0};
for (int i = 0; i < 5; i++){
e1(inputData[i]);
}
EXPECT_EQ(inputData[0], 0);
EXPECT_EQ(inputData[1], 1);
EXPECT_EQ(inputData[2], 0);
EXPECT_EQ(inputData[3], 0.5);
EXPECT_EQ(inputData[4], 0.25);
}
TEST(DelayLineEffectTest, FFandBlendTest) {
DelayLineEffect<float*> e1 {1, 1, 0, 1, 0, [](){return 0;}};
std::array<float, 5> inputData {1, 0, 0.5, 0.25, 0};
for (int i = 0; i < 5; i++) {
e1(inputData[i]);
}
EXPECT_EQ(inputData[0], 1);
EXPECT_EQ(inputData[1], 1);
EXPECT_EQ(inputData[2], 0.5);
EXPECT_EQ(inputData[3], 0.75);
EXPECT_EQ(inputData[4], 0.25);
}
}
#endif //ANDROID_FXLAB_DELAYLINEEFFECTTEST_H

View file

@ -0,0 +1,61 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_DELAYLINETEST_H
#define ANDROID_FXLAB_DELAYLINETEST_H
#include "../effects/utils/DelayLine.h"
#include <gtest/gtest.h>
namespace {
TEST(DelayLineTest, CreateAndAdd) {
DelayLine<float> d1{10};
d1.push(1.0);
EXPECT_EQ(d1[1], 1.0);
}
TEST(DelayLineTest, UnfilledAddSequence) {
DelayLine<float> d1{10};
d1.push(1.0);
d1.push(2.0);
d1.push(3.0);
EXPECT_EQ(d1[1], 3.0);
EXPECT_EQ(d1[2], 2.0);
EXPECT_EQ(d1[3], 1.0);
}
TEST(DelayLineTest, FilledAddSequence) {
DelayLine<float> d1{4};
d1.push(1.0);
d1.push(2.0);
d1.push(3.0);
d1.push(4.0);
EXPECT_EQ(d1[1], 4.0);
EXPECT_EQ(d1[2], 3.0);
EXPECT_EQ(d1[3], 2.0);
EXPECT_EQ(d1[4], 1.0);
d1.push(5.0);
EXPECT_EQ(d1[1], 5.0);
EXPECT_EQ(d1[2], 4.0);
EXPECT_EQ(d1[3], 3.0);
EXPECT_EQ(d1[4], 2.0);
d1.push(6.0);
EXPECT_EQ(d1[1], 6.0);
EXPECT_EQ(d1[2], 5.0);
EXPECT_EQ(d1[3], 4.0);
EXPECT_EQ(d1[4], 3.0);
}
} // namespace
#endif //ANDROID_FXLAB_DELAYLINETEST_H

View file

@ -0,0 +1,54 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FXLAB_TYPETESTS_H
#define ANDROID_FXLAB_TYPETESTS_H
#include <gtest/gtest.h>
#include <iostream>
#include <unistd.h>
#include "../effects/Effects.h"
#include "../FunctionList.h"
namespace {
TEST(TypeTests, Templating) {
TremoloEffect t {1, 2};
VibratoEffect<float*> v {1, 2};
float x = 5;
t(x);
auto pass = std::get<0>(EffectsTuple);
auto descrip = std::get<1>(EffectsTuple);
auto vibdes = std::get<2>(EffectsTuple);
auto gaindes = std::get<3>(EffectsTuple);
auto f = descrip.buildDefaultEffect<float*>();
auto g = vibdes.buildDefaultEffect<float*>();
auto h = vibdes.buildDefaultEffect<float*>();
f(&x, &x + 1); g(&x, &x + 1); h(&x, &x + 1);
auto j = gaindes.buildDefaultEffect<float*>();
auto k = gaindes.modifyEffect<float*>(j, std::array<float, 1> {10});
float floatArr[4] = {1,2,3, 4};
for (int i =0; i < 4; i++) {
k(floatArr + i, floatArr + i + 1);
}
auto arr = std::array<float, 1> {10};
auto data = std::array<int, 5> {1, 2, 3, 4, 5};
std::function<void(int*, int*)> fe = std::get<Effect::GainDescription>(EffectsTuple).buildEffect<int*>(arr);
fe(data.begin(), data.end());
EXPECT_EQ(data[0], 2);
}
}
#endif //ANDROID_FXLAB_TYPETESTS_H

View file

@ -0,0 +1,29 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include "DelayLineTest.h"
#include "DelayLineEffectTest.h"
#include "TypeTests.h"
// This is the runner for the various unit tests in the test directory
// Currently it is designed to be run on the development machine via CMAKE
// Since this tests effects, it should be independent of Android, and simply test locally
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}