From c93dfd7db7f7283b1f651bc65616f7f226686740 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 17 Jan 2026 22:50:35 -0500 Subject: [PATCH] Experiment with but discover that 'real' FIRs remain out of reach. --- Components/9918/Implementation/Fetch.hpp | 3 +- .../ScanTarget/Shaders/ComputeKernels.metal | 2 +- Outputs/ScanTargets/FilterGenerator.cpp | 65 +++++++++++-------- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/Components/9918/Implementation/Fetch.hpp b/Components/9918/Implementation/Fetch.hpp index 9a9062c66..652afa84f 100644 --- a/Components/9918/Implementation/Fetch.hpp +++ b/Components/9918/Implementation/Fetch.hpp @@ -286,7 +286,8 @@ private: const AddressT graphic_location = base->sprite_generator_table_address_ & bits<11>(AddressT((name << 3) | sprite.row)); sprite.image[0] = base->ram_[graphic_location]; - sprite.image[1] = base->ram_[graphic_location+16]; + sprite.image[1] = base->ram_[graphic_location+16]; // TODO: occasional out-of-bounds accesses here. Check + // uninitialised Master System. if constexpr (SpriteBuffer::test_is_filling) { if(slot == ((mode == SpriteMode::Mode2) ? 7 : 3)) { diff --git a/OSBindings/Mac/Clock Signal/ScanTarget/Shaders/ComputeKernels.metal b/OSBindings/Mac/Clock Signal/ScanTarget/Shaders/ComputeKernels.metal index 2b43aa9b9..89e74199c 100644 --- a/OSBindings/Mac/Clock Signal/ScanTarget/Shaders/ComputeKernels.metal +++ b/OSBindings/Mac/Clock Signal/ScanTarget/Shaders/ComputeKernels.metal @@ -173,7 +173,7 @@ kernel void separateLumaKernel15( return setSeparatedLumaChroma( luminanceChrominance, - centreSample.gb - half2(0.5), + centreSample.gb - half2(0.5f), centreSample.a, outTexture, gid, diff --git a/Outputs/ScanTargets/FilterGenerator.cpp b/Outputs/ScanTargets/FilterGenerator.cpp index 0d52aa736..fb2516ff2 100644 --- a/Outputs/ScanTargets/FilterGenerator.cpp +++ b/Outputs/ScanTargets/FilterGenerator.cpp @@ -30,32 +30,35 @@ float FilterGenerator::radians_per_sample() const { FilterGenerator::FilterPair FilterGenerator::separation_filter() { FilterPair result{}; - // Luminance: box. + // Luminance. result.luma = -// SignalProcessing::KaiserBessel::filter( -// max_kernel_size_, -// samples_per_line_, -// 0.0f, -// subcarrier_frequency_ * 0.25f -// ); SignalProcessing::Box::filter( radians_per_sample(), std::numbers::pi_v * 2.0f ); - // Chrominance: compute as subcarrier - luminance. - - // TODO: attempting a notch as below seems to introduce a phase shift or time delay. - // I'm not smart enough currently to understand why. - // I need to fix or, at the minimum, predict it for correction later. +// Usually provides a better luminance filter, but has issues with in-phase NTSC colour: +// +// SignalProcessing::KaiserBessel::filter( +// max_kernel_size_, +// samples_per_line_, +// 0.0f, +// subcarrier_frequency_ * 0.5f +// ); + // Chrominance. result.chroma = SignalProcessing::KaiserBessel::filter( max_kernel_size_, samples_per_line_, subcarrier_frequency_, samples_per_line_ ); - result.luma.copy_to::iterator>( + SignalProcessing::KaiserBessel::filter( + max_kernel_size_, + samples_per_line_, + 0.0f, + subcarrier_frequency_ + ).copy_to::iterator>( result.chroma.begin(), result.chroma.end(), [](const auto iterator, const float value) { @@ -69,30 +72,36 @@ FilterGenerator::FilterPair FilterGenerator::separation_filter() { FilterGenerator::FilterPair FilterGenerator::demouldation_filter() { FilterPair result{}; - result.chroma = - SignalProcessing::KaiserBessel::filter( - max_kernel_size_, - samples_per_line_, - 40.0f, - subcarrier_frequency_ * 0.5f - ) - * (decoding_path_ == DecodingPath::SVideo ? 2.0f : 0.5f); - - // S-Video: don't filter luminance at all. if(decoding_path_ == DecodingPath::SVideo) { + // S-Video: don't filter luminance at all. const float identity[] = { 1.0f }; result.luma = SignalProcessing::FIRFilter( std::begin(identity), std::end(identity) ); - return result; + } else { + // Composite: sharpen the luminance a touch. + result.luma = + SignalProcessing::KaiserBessel::filter( + max_kernel_size_, samples_per_line_, 100.0f, subcarrier_frequency_); } - // Composite: sharpen the luminance a touch. - result.luma = - SignalProcessing::KaiserBessel::filter( - max_kernel_size_, samples_per_line_, 10.0f, subcarrier_frequency_); + result.chroma = + SignalProcessing::Box::filter( + radians_per_sample(), + std::numbers::pi_v * 2.0f + ) + * (decoding_path_ == DecodingPath::SVideo ? 2.0f : 0.5f); + +// Usually provides a better chroma filter, but has issues with in-phase NTSC colour: +// +// SignalProcessing::KaiserBessel::filter( +// max_kernel_size_, +// samples_per_line_, +// 0.0f, +// subcarrier_frequency_ * 0.5f +// ) return result; }