Interpolation über drop-Outs mit eingebaut. Nun erfolgreich
This commit is contained in:
parent
109adce56c
commit
8cd333bba7
2 changed files with 75 additions and 9 deletions
|
|
@ -153,6 +153,13 @@ class EventScore
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* single sound channel with the ability to investigate itself.
|
||||||
|
* Internally holds a work buffer to be filled through libsndfile.
|
||||||
|
* The #visit function performs the decision logic to detect a defect
|
||||||
|
* at the "current" position, including the next neighbouring samples.
|
||||||
|
*/
|
||||||
class Channel
|
class Channel
|
||||||
{
|
{
|
||||||
SNDFILE *in_ = nullptr,
|
SNDFILE *in_ = nullptr,
|
||||||
|
|
@ -267,6 +274,15 @@ class Channel
|
||||||
event.recordNeutral();
|
event.recordNeutral();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** if it ain't broken, don't fix it */
|
||||||
|
bool
|
||||||
|
reallyNeedsFix()
|
||||||
|
{
|
||||||
|
float changeFactor = delta(workPos_) / (ema_ + EPSILON);
|
||||||
|
return changeFactor > 0.25 * TRIGGER_FACTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float
|
float
|
||||||
sampleLevel()
|
sampleLevel()
|
||||||
|
|
@ -351,20 +367,44 @@ class Patch
|
||||||
void
|
void
|
||||||
reconstructMirroredSignal()
|
reconstructMirroredSignal()
|
||||||
{
|
{
|
||||||
for (uint i=0; i < LEN; ++i)
|
for (size_t i=0; i < LEN; ++i)
|
||||||
workBuff[i] = rawBuff[LEN-1 - i];
|
workBuff[i] = rawBuff[LEN-1 - i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
public:
|
maybe_fix_Gap()
|
||||||
Patch (Channel& c)
|
|
||||||
: rawBuff{c.accessCurrentContext()}
|
|
||||||
{
|
{
|
||||||
reconstructMirroredSignal();
|
const size_t CENTRE = CONTEXT;
|
||||||
|
size_t i = CENTRE-1;
|
||||||
|
while (i > 0 && 0.0f == workBuff[i]) --i;
|
||||||
|
if (i < CENTRE-1)
|
||||||
|
fix_Gap_by_Interpolation(i, CENTRE);
|
||||||
|
|
||||||
|
i = CENTRE;
|
||||||
|
while (i < LEN-1 && 0.0f == workBuff[i]) ++i;
|
||||||
|
if (i > CENTRE)
|
||||||
|
fix_Gap_by_Interpolation(CENTRE-1, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
apply()
|
fix_Gap_by_Interpolation(size_t s, size_t e)
|
||||||
|
{
|
||||||
|
assert (s+1 < e);
|
||||||
|
assert (0 <= s && s+1 < LEN);
|
||||||
|
assert (0 <= e && e < LEN);
|
||||||
|
|
||||||
|
float before = workBuff[s];
|
||||||
|
float after = workBuff[e];
|
||||||
|
for (size_t i = s+1; i<e; ++i)
|
||||||
|
{
|
||||||
|
float fade = float(i-s) / float(e-s);
|
||||||
|
workBuff[i] = rawBuff[LEN-1 - i]
|
||||||
|
= (1.0-fade)*before + fade*after;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mix_faded_with_mirroredSignal()
|
||||||
{
|
{
|
||||||
for (uint i=0; i < LEN; ++i)
|
for (uint i=0; i < LEN; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -382,6 +422,21 @@ class Patch
|
||||||
rawBuff[i] = q*rawBuff[i] + p*workBuff[i];
|
rawBuff[i] = q*rawBuff[i] + p*workBuff[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
Patch (Channel& c)
|
||||||
|
: rawBuff{c.accessCurrentContext()}
|
||||||
|
{
|
||||||
|
reconstructMirroredSignal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
apply()
|
||||||
|
{
|
||||||
|
maybe_fix_Gap();
|
||||||
|
mix_faded_with_mirroredSignal();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -460,7 +515,8 @@ process()
|
||||||
{
|
{
|
||||||
cout << "PATCH at: "<< absStartPos+i <<"\n";
|
cout << "PATCH at: "<< absStartPos+i <<"\n";
|
||||||
for (Channel& channel : streams)
|
for (Channel& channel : streams)
|
||||||
Patch(channel).apply();
|
if (channel.reallyNeedsFix())
|
||||||
|
Patch(channel).apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,5 +117,15 @@ Die Wirklichkeit ist eben _widerständig_ -- einfache Methoden funktionieren nur
|
||||||
Umgebung. Hier führen also die Verschiebungen dazu, daß Ereignisse nicht, oder doppelt erkannt werden.
|
Umgebung. Hier führen also die Verschiebungen dazu, daß Ereignisse nicht, oder doppelt erkannt werden.
|
||||||
Und die im Idealfall sehr gut funktionierende Reparatur mit dem gespiegelten Signal führt bei den Null-Strecken
|
Und die im Idealfall sehr gut funktionierende Reparatur mit dem gespiegelten Signal führt bei den Null-Strecken
|
||||||
dazu, daß ein weiterer Sprung (am anderen Ende des drop-Out) _rückwärts_ in das ursprünglich saubere Signal
|
dazu, daß ein weiterer Sprung (am anderen Ende des drop-Out) _rückwärts_ in das ursprünglich saubere Signal
|
||||||
verschleppt wird. Das heitßt, in diesem Fall verschlimmert die ``Korrektur'' den Schaden.
|
verschleppt wird. Das heißt, in diesem Fall verschlimmert die ``Korrektur'' den Schaden.
|
||||||
|
|
||||||
|
.5.9.2014
|
||||||
|
Insgesamt hat erst die Kombination der verschiedenen Ansätze zum Erfolg geführt
|
||||||
|
|
||||||
|
- relativ elaborierte Entscheidungslogik, die mehrere Spuren korreliert
|
||||||
|
- Gewichtung durch die Stärke des Sprunges
|
||||||
|
- Suche auch in der nächsten Umgebung für die Korrelation
|
||||||
|
- Feinjustieren auf den maximalen Sprung in jeder bearbeiteten Spur
|
||||||
|
- zusätzliches Interpolieren über eine drop-out-Strecke
|
||||||
|
- 4.5ms langer ``Patch'' mit dem gespiegelten Signal
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue