Sample offset is adjusted every line

This commit is contained in:
Vort 2020-08-05 19:36:07 +03:00
parent 44d199cfab
commit 2e90be0044
3 changed files with 78 additions and 94 deletions

View File

@ -43,14 +43,12 @@ ATVDemodSink::ATVDemodSink() :
m_ampMin(-1.0f),
m_ampMax(1.0f),
m_ampDelta(2.0f),
m_colIndex(0),
m_sampleIndex(0),
m_sampleIndexDetected(0),
m_hSyncShiftSum(0.0f),
m_hSyncShiftCount(0),
m_sampleOffset(0),
m_sampleOffsetFrac(0.0f),
m_sampleOffsetDetected(0),
m_hSyncShift(0.0f),
m_hSyncErrorCount(0),
m_amSampleIndex(0),
m_rowIndex(0),
m_lineIndex(0),
m_ampAverage(4800),
m_bfoPLL(200/1000000, 100/1000000, 0.01),
@ -490,8 +488,6 @@ void ATVDemodSink::applyChannelSettings(int channelSampleRate, int channelFreque
}
m_fieldIndex = 0;
m_colIndex = 0;
m_rowIndex = 0;
m_channelSampleRate = channelSampleRate;
m_channelFrequencyOffset = channelFrequencyOffset;
@ -584,8 +580,6 @@ void ATVDemodSink::applySettings(const ATVDemodSettings& settings, bool force)
}
m_fieldIndex = 0;
m_colIndex = 0;
m_rowIndex = 0;
}
if ((settings.m_topTimeFactor != m_settings.m_topTimeFactor) || force) {

View File

@ -150,15 +150,14 @@ private:
float m_fltBufferI[6];
float m_fltBufferQ[6];
int m_colIndex;
int m_sampleIndex; // assumed (averaged) sample offset from the start of horizontal sync pulse
int m_sampleIndexDetected; // detected sample offset from the start of horizontal sync pulse
int m_amSampleIndex;
int m_rowIndex;
int m_amSampleIndex;
int m_sampleOffset; // assumed (averaged) sample offset from the start of horizontal sync pulse
float m_sampleOffsetFrac; // sample offset, fractional part
int m_sampleOffsetDetected; // detected sample offset from the start of horizontal sync pulse
int m_lineIndex;
float m_hSyncShiftSum;
int m_hSyncShiftCount;
float m_hSyncShift;
int m_hSyncErrorCount;
float prevSample;
@ -200,67 +199,71 @@ private:
inline void processSample(float& sample, int& sampleVideo)
{
// Filling pixel on the current line - reference index 0 at start of sync pulse
m_tvScreenData->setSampleValue(m_sampleIndex - m_numberSamplesPerHSync, sampleVideo);
m_tvScreenData->setSampleValue(m_sampleOffset - m_numberSamplesPerHSync, sampleVideo);
if (m_settings.m_hSync)
{
// Horizontal Synchro detection
if ((prevSample >= m_settings.m_levelSynchroTop &&
sample < m_settings.m_levelSynchroTop) // horizontal synchro detected
&& (m_sampleIndexDetected > m_samplesPerLine - m_numberSamplesPerHTopNom))
&& (m_sampleOffsetDetected > m_samplesPerLine - m_numberSamplesPerHTopNom))
{
double sampleIndexDetectedFrac =
float sampleOffsetDetectedFrac =
(sample - m_settings.m_levelSynchroTop) / (prevSample - sample);
double hSyncShift = -m_sampleIndex - sampleIndexDetectedFrac;
float hSyncShift = -m_sampleOffset - m_sampleOffsetFrac - sampleOffsetDetectedFrac;
if (hSyncShift > m_samplesPerLine / 2)
hSyncShift -= m_samplesPerLine;
hSyncShift -= m_samplesPerLine;
else if (hSyncShift < -m_samplesPerLine / 2)
hSyncShift += m_samplesPerLine;
hSyncShift += m_samplesPerLine;
if (fabs(hSyncShift) > m_numberSamplesPerHTopNom)
{
m_hSyncErrorCount++;
if (m_hSyncErrorCount >= 8)
if (m_hSyncErrorCount >= 4)
{
// Fast sync: shift is too large, needs to be fixed ASAP
m_sampleIndex = 0;
m_hSyncShiftSum = 0.0;
m_hSyncShiftCount = 0;
m_hSyncShift = hSyncShift;
m_hSyncErrorCount = 0;
}
}
else
{
m_hSyncShiftSum += hSyncShift;
m_hSyncShiftCount++;
// Slow sync: slight adjustment is needed
m_hSyncShift = hSyncShift * 0.2f;
m_hSyncErrorCount = 0;
}
m_sampleIndexDetected = 0;
m_sampleOffsetDetected = 0;
}
else
m_sampleIndexDetected++;
m_sampleOffsetDetected++;
}
else
{
m_hSyncShiftSum = 0.0f;
m_hSyncShiftCount = 0;
}
m_sampleIndex++;
m_sampleOffset++;
if (m_settings.m_vSync)
{
if (m_sampleIndex > m_fieldDetectStartPos && m_sampleIndex < m_fieldDetectEndPos)
if (m_sampleOffset > m_fieldDetectStartPos && m_sampleOffset < m_fieldDetectEndPos)
m_fieldDetectSampleCount += sample < m_settings.m_levelSynchroTop;
if (m_sampleIndex > m_vSyncDetectStartPos && m_sampleIndex < m_vSyncDetectEndPos)
if (m_sampleOffset > m_vSyncDetectStartPos && m_sampleOffset < m_vSyncDetectEndPos)
m_vSyncDetectSampleCount += sample < m_settings.m_levelSynchroTop;
}
// end of line
if (m_sampleIndex >= m_samplesPerLine)
if (m_sampleOffset >= m_samplesPerLine)
{
m_sampleIndex = 0;
if (m_settings.m_hSync)
{
float sampleOffsetFloat = m_hSyncShift + m_sampleOffsetFrac;
m_sampleOffset = sampleOffsetFloat;
m_sampleOffsetFrac = sampleOffsetFloat - m_sampleOffset;
}
else
{
m_sampleOffset = 0;
}
m_hSyncShift = 0.0f;
if (m_settings.m_atvStd == ATVDemodSettings::ATVStdHSkip) {
m_lineIndex++;
if (m_settings.m_atvStd == ATVDemodSettings::ATVStdHSkip) {
processEOLHSkip();
} else {
processEOLClassic();
@ -273,24 +276,9 @@ private:
// Standard vertical sync
inline void processEOLClassic()
{
m_lineIndex++;
if (m_lineIndex == m_numberOfVSyncLines + 3 && m_fieldIndex == 0)
{
float shiftSamples = 0.0f;
// Slow sync: slight adjustment is needed
if (m_hSyncShiftCount != 0 && m_settings.m_hSync)
{
shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount;
m_sampleIndex = shiftSamples;
m_hSyncShiftSum = 0.0f;
m_hSyncShiftCount = 0;
m_hSyncErrorCount = 0;
}
m_registeredTVScreen->renderImage();
//m_registeredTVScreen->renderImage(0,
// shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples));
}
if (m_vSyncDetectSampleCount > m_vSyncDetectThreshold &&
@ -323,47 +311,21 @@ private:
if (m_interleaved)
rowIndex = rowIndex * 2 - m_fieldIndex;
// TODO: CHANGE
float shiftSamples = 0.0f;
if (m_hSyncShiftCount != 0)
shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount;
m_tvScreenData->selectRow(rowIndex,
shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples));
m_tvScreenData->selectRow(rowIndex, m_sampleOffsetFrac);
}
// Vertical sync is obtained by skipping horizontal sync on the line that triggers vertical sync (new frame)
inline void processEOLHSkip()
{
m_lineIndex++;
m_rowIndex++;
if ((m_sampleIndexDetected > (3*m_samplesPerLine) / 2) // Vertical sync is first horizontal sync after skip (count at least 1.5 line length)
if ((m_sampleOffsetDetected > (3 * m_samplesPerLine) / 2) // Vertical sync is first horizontal sync after skip (count at least 1.5 line length)
|| (!m_settings.m_vSync && (m_lineIndex >= m_settings.m_nbLines))) // Vsync ignored and reached nominal number of lines per frame
{
float shiftSamples = 0.0f;
// Slow sync: slight adjustment is needed
if (m_hSyncShiftCount != 0 && m_settings.m_hSync)
{
shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount;
m_sampleIndex = shiftSamples;
m_hSyncShiftSum = 0.0f;
m_hSyncShiftCount = 0;
m_hSyncErrorCount = 0;
}
m_registeredTVScreen->renderImage();
//m_registeredTVScreen->renderImage(0,
// shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples));
m_lineIndex = 0;
m_rowIndex = 0;
m_lineIndex = 0;
}
// TODO: CHANGE
float shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount;
m_tvScreenData->setSampleValue(m_rowIndex,
shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples));
m_tvScreenData->selectRow(m_lineIndex, m_sampleOffsetFrac);
}
};
#endif // INCLUDE_ATVDEMODSINK_H

View File

@ -104,10 +104,34 @@ void TVScreenAnalog::initializeGL()
{
initializeOpenGLFunctions();
connect(QOpenGLContext::currentContext(), &QOpenGLContext::aboutToBeDestroyed,
this, &TVScreenAnalog::cleanup); // TODO: when migrating to QOpenGLWidget
m_shader = std::make_shared<QOpenGLShaderProgram>(this);
m_shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
m_shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
m_shader->link();
if (!m_shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource))
{
qWarning()
<< "TVScreenAnalog::initializeGL: error in vertex shader:"
<< m_shader->log();
m_shader = nullptr;
return;
}
if (!m_shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource))
{
qWarning()
<< "TVScreenAnalog::initializeGL: error in fragment shader:"
<< m_shader->log();
m_shader = nullptr;
return;
}
if (!m_shader->link())
{
qWarning()
<< "TVScreenAnalog::initializeGL: error linking shader:"
<< m_shader->log();
m_shader = nullptr;
return;
}
m_vertexAttribIndex = m_shader->attributeLocation("vertex");
m_texCoordAttribIndex = m_shader->attributeLocation("texCoord");
@ -117,9 +141,6 @@ void TVScreenAnalog::initializeGL()
m_imageHeightLoc = m_shader->uniformLocation("imh");
m_texelWidthLoc = m_shader->uniformLocation("tlw");
m_texelHeightLoc = m_shader->uniformLocation("tlh");
connect(QOpenGLContext::currentContext(), &QOpenGLContext::aboutToBeDestroyed,
this, &TVScreenAnalog::cleanup); // TODO: when migrating to QOpenGLWidget
}
void TVScreenAnalog::initializeTextures()
@ -162,6 +183,13 @@ void TVScreenAnalog::paintGL()
{
m_isDataChanged = false;
if (!m_shader)
{
glClearColor(0.2f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
return;
}
if (!m_imageTexture ||
m_imageTexture->width() != m_data->getWidth() ||
m_imageTexture->height() != m_data->getHeight())
@ -192,7 +220,7 @@ void TVScreenAnalog::paintGL()
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
1, m_data->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, m_data->getLineShiftData());
float rectHalfWidth = 1.0f + 4 * texelWidth;
float rectHalfWidth = 1.0f + 4.0f / (imageWidth - 4.0f);
GLfloat vertices[] =
{
-rectHalfWidth, -1.0f,