provide a scratch buffer

This commit is contained in:
Ahmet Inan 2024-04-24 23:15:33 +02:00
parent b24e7d0730
commit 558120116d
7 changed files with 54 additions and 52 deletions

View file

@ -12,6 +12,7 @@ public class Decoder {
private final Demodulator demodulator;
private final float[] scanLineBuffer;
private final float[] scratchBuffer;
private final int[] evenBuffer;
private final int[] oddBuffer;
private final int[] scopePixels;
@ -51,6 +52,7 @@ public class Decoder {
double scanLineMaxSeconds = 7;
int scanLineMaxSamples = (int) Math.round(scanLineMaxSeconds * sampleRate);
scanLineBuffer = new float[scanLineMaxSamples];
scratchBuffer = new float[sampleRate];
int scanLineCount = 4;
last5msScanLines = new int[scanLineCount];
last9msScanLines = new int[scanLineCount];
@ -171,10 +173,10 @@ public class Decoder {
int extrapolate = endPulse / scanLineSamples;
int firstPulse = endPulse - extrapolate * scanLineSamples;
for (int pulseIndex = firstPulse; pulseIndex < endPulse; pulseIndex += scanLineSamples)
copyLines(mode.decodeScanLine(evenBuffer, oddBuffer, scanLineBuffer, pulseIndex, scanLineSamples, frequencyOffset));
copyLines(mode.decodeScanLine(evenBuffer, oddBuffer, scratchBuffer, scanLineBuffer, pulseIndex, scanLineSamples, frequencyOffset));
}
for (int i = pictureChanged ? 0 : lines.length - 1; i < lines.length; ++i)
copyLines(mode.decodeScanLine(evenBuffer, oddBuffer, scanLineBuffer, pulses[i], lines[i], frequencyOffset));
copyLines(mode.decodeScanLine(evenBuffer, oddBuffer, scratchBuffer, scanLineBuffer, pulses[i], lines[i], frequencyOffset));
int shift = pulses[pulses.length - 1] - scanLineReserveSamples;
if (shift > scanLineReserveSamples) {
adjustSyncPulses(last5msSyncPulses, shift);
@ -219,7 +221,7 @@ public class Decoder {
return processSyncPulse(syncPulse20msModes, last20msFrequencyOffsets, last20msSyncPulses, last20msScanLines, syncPulseIndex);
}
} else if (lastSyncPulseIndex >= scanLineReserveSamples && curSample > lastSyncPulseIndex + (lastScanLineSamples * 5) / 4) {
copyLines(lastMode.decodeScanLine(evenBuffer, oddBuffer, scanLineBuffer, lastSyncPulseIndex, lastScanLineSamples, lastFrequencyOffset));
copyLines(lastMode.decodeScanLine(evenBuffer, oddBuffer, scratchBuffer, scanLineBuffer, lastSyncPulseIndex, lastScanLineSamples, lastFrequencyOffset));
lastSyncPulseIndex += lastScanLineSamples;
return true;
}

View file

@ -11,5 +11,5 @@ public interface Mode {
int getScanLineSamples();
int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scanLineBuffer, int prevPulseIndex, int scanLineSamples, float frequencyOffset);
int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scratchBuffer, float[] scanLineBuffer, int syncPulseIndex, int scanLineSamples, float frequencyOffset);
}

View file

@ -55,24 +55,24 @@ public class PaulDon implements Mode {
}
@Override
public int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scanLineBuffer, int prevPulseIndex, int scanLineSamples, float frequencyOffset) {
if (prevPulseIndex + beginSamples < 0 || prevPulseIndex + endSamples > scanLineBuffer.length)
public int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scratchBuffer, float[] scanLineBuffer, int syncPulseIndex, int scanLineSamples, float frequencyOffset) {
if (syncPulseIndex + beginSamples < 0 || syncPulseIndex + endSamples > scanLineBuffer.length)
return 0;
lowPassFilter.cutoff(evenBuffer.length, 2 * channelSamples, 2);
lowPassFilter.reset();
for (int i = prevPulseIndex + beginSamples; i < prevPulseIndex + endSamples; ++i)
scanLineBuffer[i] = lowPassFilter.avg(scanLineBuffer[i]);
for (int i = beginSamples; i < endSamples; ++i)
scratchBuffer[i] = lowPassFilter.avg(scanLineBuffer[syncPulseIndex + i]);
lowPassFilter.reset();
for (int i = prevPulseIndex + endSamples - 1; i >= prevPulseIndex + beginSamples; --i)
scanLineBuffer[i] = freqToLevel(lowPassFilter.avg(scanLineBuffer[i]), frequencyOffset);
for (int i = endSamples - 1; i >= beginSamples; --i)
scratchBuffer[i] = freqToLevel(lowPassFilter.avg(scratchBuffer[i]), frequencyOffset);
for (int i = 0; i < evenBuffer.length; ++i) {
int position = (i * channelSamples) / evenBuffer.length + prevPulseIndex;
int position = (i * channelSamples) / evenBuffer.length;
int yEvenPos = position + yEvenBeginSamples;
int vAvgPos = position + vAvgBeginSamples;
int uAvgPos = position + uAvgBeginSamples;
int yOddPos = position + yOddBeginSamples;
evenBuffer[i] = ColorConverter.YUV2RGB(scanLineBuffer[yEvenPos], scanLineBuffer[uAvgPos], scanLineBuffer[vAvgPos]);
oddBuffer[i] = ColorConverter.YUV2RGB(scanLineBuffer[yOddPos], scanLineBuffer[uAvgPos], scanLineBuffer[vAvgPos]);
evenBuffer[i] = ColorConverter.YUV2RGB(scratchBuffer[yEvenPos], scratchBuffer[uAvgPos], scratchBuffer[vAvgPos]);
oddBuffer[i] = ColorConverter.YUV2RGB(scratchBuffer[yOddPos], scratchBuffer[uAvgPos], scratchBuffer[vAvgPos]);
}
return 2;
}

View file

@ -48,21 +48,21 @@ public class RGBDecoder implements Mode {
}
@Override
public int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scanLineBuffer, int prevPulseIndex, int scanLineSamples, float frequencyOffset) {
if (prevPulseIndex + beginSamples < 0 || prevPulseIndex + endSamples > scanLineBuffer.length)
public int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scratchBuffer, float[] scanLineBuffer, int syncPulseIndex, int scanLineSamples, float frequencyOffset) {
if (syncPulseIndex + beginSamples < 0 || syncPulseIndex + endSamples > scanLineBuffer.length)
return 0;
lowPassFilter.cutoff(evenBuffer.length, 2 * greenSamples, 2);
lowPassFilter.reset();
for (int i = prevPulseIndex + beginSamples; i < prevPulseIndex + endSamples; ++i)
scanLineBuffer[i] = lowPassFilter.avg(scanLineBuffer[i]);
for (int i = beginSamples; i < endSamples; ++i)
scratchBuffer[i] = lowPassFilter.avg(scanLineBuffer[syncPulseIndex + i]);
lowPassFilter.reset();
for (int i = prevPulseIndex + endSamples - 1; i >= prevPulseIndex + beginSamples; --i)
scanLineBuffer[i] = freqToLevel(lowPassFilter.avg(scanLineBuffer[i]), frequencyOffset);
for (int i = endSamples - 1; i >= beginSamples; --i)
scratchBuffer[i] = freqToLevel(lowPassFilter.avg(scratchBuffer[i]), frequencyOffset);
for (int i = 0; i < evenBuffer.length; ++i) {
int redPos = redBeginSamples + (i * redSamples) / evenBuffer.length + prevPulseIndex;
int greenPos = greenBeginSamples + (i * greenSamples) / evenBuffer.length + prevPulseIndex;
int bluePos = blueBeginSamples + (i * blueSamples) / evenBuffer.length + prevPulseIndex;
evenBuffer[i] = ColorConverter.RGB(scanLineBuffer[redPos], scanLineBuffer[greenPos], scanLineBuffer[bluePos]);
int redPos = redBeginSamples + (i * redSamples) / evenBuffer.length;
int greenPos = greenBeginSamples + (i * greenSamples) / evenBuffer.length;
int bluePos = blueBeginSamples + (i * blueSamples) / evenBuffer.length;
evenBuffer[i] = ColorConverter.RGB(scratchBuffer[redPos], scratchBuffer[greenPos], scratchBuffer[bluePos]);
}
return 1;
}

View file

@ -28,19 +28,19 @@ public class RawDecoder implements Mode {
}
@Override
public int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scanLineBuffer, int prevPulseIndex, int scanLineSamples, float frequencyOffset) {
if (prevPulseIndex < 0 || prevPulseIndex + scanLineSamples > scanLineBuffer.length)
public int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scratchBuffer, float[] scanLineBuffer, int syncPulseIndex, int scanLineSamples, float frequencyOffset) {
if (syncPulseIndex < 0 || syncPulseIndex + scanLineSamples > scanLineBuffer.length)
return 0;
lowPassFilter.cutoff(evenBuffer.length, 2 * scanLineSamples, 2);
lowPassFilter.reset();
for (int i = prevPulseIndex; i < prevPulseIndex + scanLineSamples; ++i)
scanLineBuffer[i] = lowPassFilter.avg(scanLineBuffer[i]);
for (int i = 0; i < scanLineSamples; ++i)
scratchBuffer[i] = lowPassFilter.avg(scanLineBuffer[syncPulseIndex + i]);
lowPassFilter.reset();
for (int i = prevPulseIndex + scanLineSamples - 1; i >= prevPulseIndex; --i)
scanLineBuffer[i] = freqToLevel(lowPassFilter.avg(scanLineBuffer[i]), frequencyOffset);
for (int i = scanLineSamples - 1; i >= 0; --i)
scratchBuffer[i] = freqToLevel(lowPassFilter.avg(scratchBuffer[i]), frequencyOffset);
for (int i = 0; i < evenBuffer.length; ++i) {
int position = (i * scanLineSamples) / evenBuffer.length + prevPulseIndex;
evenBuffer[i] = ColorConverter.GRAY(scanLineBuffer[position]);
int position = (i * scanLineSamples) / evenBuffer.length;
evenBuffer[i] = ColorConverter.GRAY(scratchBuffer[position]);
}
return 1;
}

View file

@ -60,12 +60,12 @@ public class Robot_36_Color implements Mode {
}
@Override
public int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scanLineBuffer, int prevPulseIndex, int scanLineSamples, float frequencyOffset) {
if (prevPulseIndex + beginSamples < 0 || prevPulseIndex + endSamples > scanLineBuffer.length)
public int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scratchBuffer, float[] scanLineBuffer, int syncPulseIndex, int scanLineSamples, float frequencyOffset) {
if (syncPulseIndex + beginSamples < 0 || syncPulseIndex + endSamples > scanLineBuffer.length)
return 0;
float separator = 0;
for (int i = 0; i < separatorSamples; ++i)
separator += scanLineBuffer[prevPulseIndex + separatorBeginSamples + i];
separator += scanLineBuffer[syncPulseIndex + separatorBeginSamples + i];
separator /= separatorSamples;
separator -= frequencyOffset;
boolean even = separator < 0;
@ -74,19 +74,19 @@ public class Robot_36_Color implements Mode {
lastEven = even;
lowPassFilter.cutoff(evenBuffer.length, 2 * luminanceSamples, 2);
lowPassFilter.reset();
for (int i = prevPulseIndex + beginSamples; i < prevPulseIndex + endSamples; ++i)
scanLineBuffer[i] = lowPassFilter.avg(scanLineBuffer[i]);
for (int i = beginSamples; i < endSamples; ++i)
scratchBuffer[i] = lowPassFilter.avg(scanLineBuffer[syncPulseIndex + i]);
lowPassFilter.reset();
for (int i = prevPulseIndex + endSamples - 1; i >= prevPulseIndex + beginSamples; --i)
scanLineBuffer[i] = freqToLevel(lowPassFilter.avg(scanLineBuffer[i]), frequencyOffset);
for (int i = endSamples - 1; i >= beginSamples; --i)
scratchBuffer[i] = freqToLevel(lowPassFilter.avg(scratchBuffer[i]), frequencyOffset);
for (int i = 0; i < evenBuffer.length; ++i) {
int luminancePos = luminanceBeginSamples + (i * luminanceSamples) / evenBuffer.length + prevPulseIndex;
int chrominancePos = chrominanceBeginSamples + (i * chrominanceSamples) / evenBuffer.length + prevPulseIndex;
int luminancePos = luminanceBeginSamples + (i * luminanceSamples) / evenBuffer.length;
int chrominancePos = chrominanceBeginSamples + (i * chrominanceSamples) / evenBuffer.length;
if (even) {
evenBuffer[i] = ColorConverter.RGB(scanLineBuffer[luminancePos], 0, scanLineBuffer[chrominancePos]);
evenBuffer[i] = ColorConverter.RGB(scratchBuffer[luminancePos], 0, scratchBuffer[chrominancePos]);
} else {
int evenYUV = evenBuffer[i];
int oddYUV = ColorConverter.RGB(scanLineBuffer[luminancePos], scanLineBuffer[chrominancePos], 0);
int oddYUV = ColorConverter.RGB(scratchBuffer[luminancePos], scratchBuffer[chrominancePos], 0);
evenBuffer[i] = ColorConverter.YUV2RGB((evenYUV & 0x00ff00ff) | (oddYUV & 0x0000ff00));
oddBuffer[i] = ColorConverter.YUV2RGB((oddYUV & 0x00ffff00) | (evenYUV & 0x000000ff));
}

View file

@ -58,21 +58,21 @@ public class Robot_72_Color implements Mode {
}
@Override
public int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scanLineBuffer, int prevPulseIndex, int scanLineSamples, float frequencyOffset) {
if (prevPulseIndex + beginSamples < 0 || prevPulseIndex + endSamples > scanLineBuffer.length)
public int decodeScanLine(int[] evenBuffer, int[] oddBuffer, float[] scratchBuffer, float[] scanLineBuffer, int syncPulseIndex, int scanLineSamples, float frequencyOffset) {
if (syncPulseIndex + beginSamples < 0 || syncPulseIndex + endSamples > scanLineBuffer.length)
return 0;
lowPassFilter.cutoff(evenBuffer.length, 2 * luminanceSamples, 2);
lowPassFilter.reset();
for (int i = prevPulseIndex + beginSamples; i < prevPulseIndex + endSamples; ++i)
scanLineBuffer[i] = lowPassFilter.avg(scanLineBuffer[i]);
for (int i = beginSamples; i < endSamples; ++i)
scratchBuffer[i] = lowPassFilter.avg(scanLineBuffer[syncPulseIndex + i]);
lowPassFilter.reset();
for (int i = prevPulseIndex + endSamples - 1; i >= prevPulseIndex + beginSamples; --i)
scanLineBuffer[i] = freqToLevel(lowPassFilter.avg(scanLineBuffer[i]), frequencyOffset);
for (int i = endSamples - 1; i >= beginSamples; --i)
scratchBuffer[i] = freqToLevel(lowPassFilter.avg(scratchBuffer[i]), frequencyOffset);
for (int i = 0; i < evenBuffer.length; ++i) {
int yPos = yBeginSamples + (i * luminanceSamples) / evenBuffer.length + prevPulseIndex;
int uPos = uBeginSamples + (i * chrominanceSamples) / evenBuffer.length + prevPulseIndex;
int vPos = vBeginSamples + (i * chrominanceSamples) / evenBuffer.length + prevPulseIndex;
evenBuffer[i] = ColorConverter.YUV2RGB(scanLineBuffer[yPos], scanLineBuffer[uPos], scanLineBuffer[vPos]);
int yPos = yBeginSamples + (i * luminanceSamples) / evenBuffer.length;
int uPos = uBeginSamples + (i * chrominanceSamples) / evenBuffer.length;
int vPos = vBeginSamples + (i * chrominanceSamples) / evenBuffer.length;
evenBuffer[i] = ColorConverter.YUV2RGB(scratchBuffer[yPos], scratchBuffer[uPos], scratchBuffer[vPos]);
}
return 1;
}