1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-08 14:25:05 +00:00

Corrects S-Video and composite generation for RGB[1/2/4] sources.

Also toys with a double luminance filter in order to try to sharpen chrominance. But maybe I should be looking at other convolutions entirely?
This commit is contained in:
Thomas Harte
2020-09-02 19:13:54 -04:00
parent 6ef1dfd8be
commit 8bab9d5d60
2 changed files with 19 additions and 9 deletions

View File

@@ -540,7 +540,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
uniforms()->cyclesMultiplier = 1.0f; uniforms()->cyclesMultiplier = 1.0f;
if(_pipeline != Pipeline::DirectToDisplay) { if(_pipeline != Pipeline::DirectToDisplay) {
// Pick a suitable cycle multiplier. // Pick a suitable cycle multiplier. TODO: can I reduce this from a multiple of 4?
const float minimumSize = 4.0f * float(modals.colour_cycle_numerator) / float(modals.colour_cycle_denominator); const float minimumSize = 4.0f * float(modals.colour_cycle_numerator) / float(modals.colour_cycle_denominator);
while(uniforms()->cyclesMultiplier * modals.cycles_per_line < minimumSize) { while(uniforms()->cyclesMultiplier * modals.cycles_per_line < minimumSize) {
uniforms()->cyclesMultiplier += 1.0f; uniforms()->cyclesMultiplier += 1.0f;
@@ -568,18 +568,28 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
{ {
auto *const chromaCoefficients = uniforms()->chromaCoefficients; auto *const chromaCoefficients = uniforms()->chromaCoefficients;
SignalProcessing::FIRFilter chrominancefilter(15, float(_lineBufferPixelsPerLine), 0.0f, colourCyclesPerLine * 0.25f); // * (isSVideoOutput ? 1.0f : 0.25f) SignalProcessing::FIRFilter chrominancefilter(15, float(_lineBufferPixelsPerLine), 0.0f, colourCyclesPerLine * 0.25f); // * (isSVideoOutput ? 1.0f : 0.25f)
const auto calculatedCoefficients = chrominancefilter.get_coefficients(); const auto calculatedChromaCoefficients = chrominancefilter.get_coefficients();
for(size_t c = 0; c < 8; ++c) { for(size_t c = 0; c < 8; ++c) {
chromaCoefficients[c].y = chromaCoefficients[c].z = calculatedCoefficients[c] * (isSVideoOutput ? 4.0f : 4.0f); chromaCoefficients[c].y = chromaCoefficients[c].z = calculatedChromaCoefficients[c] * (isSVideoOutput ? 4.0f : 4.0f);
chromaCoefficients[c].x = 0.0f; chromaCoefficients[c].x = 0.0f;
} }
chromaCoefficients[7].x = 1.0f; chromaCoefficients[7].x = 1.0f;
// Luminance is under-filtered during the separation phase in order not to subtract too much from chrominance;
// therefore an additional filtering is applied here.
if(!isSVideoOutput) {
SignalProcessing::FIRFilter luminancefilter(15, float(_lineBufferPixelsPerLine), 0.0f, colourCyclesPerLine);
const auto calculatedLumaCoefficients = luminancefilter.get_coefficients();
for(size_t c = 0; c < 8; ++c) {
chromaCoefficients[c].x = calculatedLumaCoefficients[c];
}
}
} }
// Generate the luminance filter. // Generate the luminance separation filter.
{ {
auto *const luminanceCoefficients = uniforms()->lumaCoefficients; auto *const luminanceCoefficients = uniforms()->lumaCoefficients;
SignalProcessing::FIRFilter luminancefilter(15, float(_lineBufferPixelsPerLine), 0.0f, colourCyclesPerLine); SignalProcessing::FIRFilter luminancefilter(15, float(_lineBufferPixelsPerLine), 0.0f, colourCyclesPerLine * 1.25f);
const auto calculatedCoefficients = luminancefilter.get_coefficients(); const auto calculatedCoefficients = luminancefilter.get_coefficients();
memcpy(luminanceCoefficients, calculatedCoefficients.data(), sizeof(float)*8); memcpy(luminanceCoefficients, calculatedCoefficients.data(), sizeof(float)*8);
} }

View File

@@ -295,7 +295,7 @@ float3 convertRed1Green1Blue1(SourceInterpolator vert, texture2d<ushort> texture
} \ } \
\ \
fragment float4 svideoSample##name(SourceInterpolator vert [[stage_in]], texture2d<pixelType> texture [[texture(0)]], constant Uniforms &uniforms [[buffer(0)]]) { \ fragment float4 svideoSample##name(SourceInterpolator vert [[stage_in]], texture2d<pixelType> texture [[texture(0)]], constant Uniforms &uniforms [[buffer(0)]]) { \
const auto colour = uniforms.fromRGB * convert##name(vert, texture); \ const auto colour = uniforms.fromRGB * clamp(convert##name(vert, texture), float(0.0f), float(1.0f)); \
const float2 qam = quadrature(vert.colourPhase); \ const float2 qam = quadrature(vert.colourPhase); \
const float chroma = dot(colour.gb, qam); \ const float chroma = dot(colour.gb, qam); \
return float4( \ return float4( \
@@ -306,7 +306,7 @@ float3 convertRed1Green1Blue1(SourceInterpolator vert, texture2d<ushort> texture
} \ } \
\ \
fragment float4 compositeSample##name(SourceInterpolator vert [[stage_in]], texture2d<pixelType> texture [[texture(0)]], constant Uniforms &uniforms [[buffer(0)]]) { \ fragment float4 compositeSample##name(SourceInterpolator vert [[stage_in]], texture2d<pixelType> texture [[texture(0)]], constant Uniforms &uniforms [[buffer(0)]]) { \
const auto colour = uniforms.fromRGB * convert##name(vert, texture); \ const auto colour = uniforms.fromRGB * clamp(convert##name(vert, texture), float3(0.0f), float3(1.0f)); \
const float2 colourSubcarrier = quadrature(vert.colourPhase); \ const float2 colourSubcarrier = quadrature(vert.colourPhase); \
const float level = mix(colour.r, dot(colour.gb, colourSubcarrier), vert.colourAmplitude); \ const float level = mix(colour.r, dot(colour.gb, colourSubcarrier), vert.colourAmplitude); \
return float4( \ return float4( \
@@ -442,10 +442,10 @@ kernel void separateLumaKernel( texture2d<float, access::read> inTexture [[textu
#undef Sample #undef Sample
// TODO: determine why centreSample.a doesn't seem to be giving the real composite amplitude, and stop // TODO: determine why centreSample.a doesn't seem to be giving the real composite amplitude, and stop
// hard-coding 0.15f below. // hard-coding 0.15f and 7.0f below.
outTexture.write(float4( outTexture.write(float4(
luminance / (1.0f - 0.15f), luminance / (1.0f - 0.15f),
(centreSample.gb - float2(0.5f)) * (centreSample.r - luminance) + float2(0.5f), (centreSample.gb - float2(0.5f)) * (centreSample.r - luminance) * 28.0f + float2(0.5f),
1.0f 1.0f
), ),
gid + uint2(7, offset)); gid + uint2(7, offset));