1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#include "effects/backends/builtin/glitcheffect.h"
#include <QtDebug>
#include "util/math.h"
#include "util/sample.h"
QString GlitchEffect::getId() {
return "org.mixxx.effects.glitch";
}
EffectManifestPointer GlitchEffect::getManifest() {
EffectManifestPointer pManifest(new EffectManifest());
pManifest->setAddDryToWet(false);
pManifest->setEffectRampsFromDry(false);
pManifest->setId(getId());
pManifest->setName(QObject::tr("Glitch"));
pManifest->setShortName(QObject::tr("Glitch"));
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(
QObject::tr("Periodically samples and repeats a small portion of "
"audio to create a glitchy metallic sound."));
EffectManifestParameterPointer delay = pManifest->addParameter();
delay->setId("delay_time");
delay->setName(QObject::tr("Time"));
delay->setShortName(QObject::tr("Time"));
delay->setDescription(QObject::tr(
"Delay time\n"
"1/8 - 2 beats if tempo is detected\n"
"1/8 - 2 seconds if no tempo is detected"));
delay->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
delay->setUnitsHint(EffectManifestParameter::UnitsHint::Beats);
delay->setRange(0.0, 0.5, 2.0);
EffectManifestParameterPointer quantize = pManifest->addParameter();
quantize->setId("quantize");
quantize->setName(QObject::tr("Quantize"));
quantize->setShortName(QObject::tr("Quantize"));
quantize->setDescription(QObject::tr(
"Round the Time parameter to the nearest 1/8 beat."));
quantize->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
quantize->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
quantize->setRange(0, 1, 1);
EffectManifestParameterPointer triplet = pManifest->addParameter();
triplet->setId("triplet");
triplet->setName(QObject::tr("Triplets"));
triplet->setShortName(QObject::tr("Triplets"));
triplet->setDescription(
QObject::tr("When the Quantize parameter is enabled, divide "
"rounded 1/8 beats of Time parameter by 3."));
triplet->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
triplet->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
triplet->setRange(0, 0, 1);
return pManifest;
}
void GlitchEffect::loadEngineEffectParameters(
const QMap<QString, EngineEffectParameterPointer>& parameters) {
m_pDelayParameter = parameters.value("delay_time");
m_pQuantizeParameter = parameters.value("quantize");
m_pTripletParameter = parameters.value("triplet");
}
void GlitchEffect::processChannel(
GlitchGroupState* pGroupState,
const CSAMPLE* pInput,
CSAMPLE* pOutput,
const mixxx::EngineParameters& engineParameters,
const EffectEnableState enableState,
const GroupFeatureState& groupFeatures) {
// The minimum of the parameter is zero so the exact center of the knob is 1 beat.
double period = m_pDelayParameter->value();
int delay_frames;
double min_delay;
if (groupFeatures.has_beat_length_sec) {
if (m_pQuantizeParameter->toBool()) {
period = roundToFraction(period, 8);
if (m_pTripletParameter->toBool()) {
period /= 3.0;
}
}
period = std::max(period, 1 / 8.0);
delay_frames = static_cast<int>(period * groupFeatures.beat_length_sec *
engineParameters.sampleRate());
min_delay = 1 / 8.0 * groupFeatures.beat_length_sec * engineParameters.sampleRate();
} else {
delay_frames = static_cast<int>(period * engineParameters.sampleRate());
min_delay = 1 / 8.0 * engineParameters.sampleRate();
}
if (delay_frames < min_delay) {
SampleUtil::copy(
pOutput,
pInput,
engineParameters.samplesPerBuffer());
return;
}
int delay_samples = delay_frames * engineParameters.channelCount();
pGroupState->sample_count += engineParameters.samplesPerBuffer();
if (pGroupState->sample_count >= delay_samples) {
if (m_pDelayParameter->value() < 2.0) {
SampleUtil::copy(pGroupState->repeat_buf.data(),
pInput,
engineParameters.samplesPerBuffer());
}
pGroupState->sample_count = 0;
}
SampleUtil::copy(
pOutput,
pGroupState->repeat_buf.data(),
engineParameters.samplesPerBuffer());
}
|