First check-in of Blargg NTSC filtering code. It does compile, but

doesn't do much else ATM.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2392 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2012-02-23 20:30:58 +00:00
parent cf10e216f4
commit 959b5c6dba
3 changed files with 623 additions and 0 deletions

View File

@ -0,0 +1,452 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2012 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifdef DISPLAY_TV
#include "NTSCFilter.hxx"
#include <cstring>
#include <cmath>
#include <cstdlib>
static float const rgb_unit = 0x1000;
static float const pi = 3.14159265358979323846f;
/* important to use + and not | since values are signed */
#define MAKE_KRGB( r, g, b ) \
( ((r + 16) >> 5 << 20) + ((g + 16) >> 5 << 10) + ((b + 16) >> 5) )
#define MAKE_KMASK( x ) (((x) << 20) | ((x) << 10) | (x))
/* clamp each RGB component to 0 to 0x7F range (low two bits are trashed) */
#define CLAMP_RGB( io, adj ) {\
ntsc_rgb_t sub = (io) >> (7 + adj) & MAKE_KMASK( 3 );\
ntsc_rgb_t clamp = MAKE_KMASK( 0x202 ) - sub;\
io = ((io) | clamp) & (clamp - sub);\
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NTSCFilter::NTSCFilter()
: myNTSCEmu(NULL),
myCurrentModeNum(-1)
{
// Add various presets
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NTSCFilter::~NTSCFilter()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string& NTSCFilter::next()
{
return EmptyString;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::atari_ntsc_init(atari_ntsc_setup_t const* setup)
{
/* init pixel renderer */
int entry;
float burst_phase = (setup->burst_phase) * pi;
ntsc_to_rgb_t ntsc;
ntsc_to_rgb_init( &ntsc, setup, setup->hue * pi - burst_phase );
for ( entry = 0; entry < atari_ntsc_color_count; entry++ )
{
/*NTSC PHASE CONSTANTS.*/
float ntsc_phase_constant[16]={0,2.27,1.87,1.62,
1.22,0.62,-0.31,-0.855,
-1.18,-1.43,-1.63,-1.93,
-2.38,-3.43,2.52,2.07};
/*NTSC luma multipliers from gtia.pdf*/
float luma_mult[16]={
0.6941, 0.7091, 0.7241, 0.7401,
0.7560, 0.7741, 0.7931, 0.8121,
0.8260, 0.8470, 0.8700, 0.8930,
0.9160, 0.9420, 0.9690, 1.0000};
/* calculate yiq for color entry */
int color = entry >> 4;
float angle = burst_phase + ntsc_phase_constant[color];
float lumafactor = ( luma_mult[ entry & 0x0f] - luma_mult[0] )/( luma_mult[15] - luma_mult[0] );
float adj_lumafactor = pow(lumafactor, 1 +setup->gamma_adj);
float y = adj_lumafactor * rgb_unit;
float base_saturation = (color ? rgb_unit * 0.35f: 0.0f);
float saturation_ramp = setup->saturation_ramp;
float saturation = base_saturation * ( 1 - saturation_ramp*lumafactor );
float i = sin( angle ) * saturation;
float q = cos( angle ) * saturation;
ntsc_rgb_t* out = myNTSCEmu->table [entry];
y = y * ntsc.contrast + ntsc.brightness;
/* generate at four alignments with respect to output */
ntsc.composite [composite_border + 0] = i + y;
ntsc.composite [composite_border + 1] = q + y;
out = gen_pixel( &ntsc, 0, 0, out );
ntsc.composite [composite_border + 0] = 0;
ntsc.composite [composite_border + 1] = 0;
ntsc.composite [composite_border + 2] = i - y;
ntsc.composite [composite_border + 3] = q - y;
out = gen_pixel( &ntsc, 2, 2, out );
ntsc.composite [composite_border + 2] = 0;
ntsc.composite [composite_border + 3] = 0;
ntsc.composite [composite_border + 4] = i + y;
ntsc.composite [composite_border + 5] = q + y;
out = gen_pixel( &ntsc, 4, 4, out );
ntsc.composite [composite_border + 4] = 0;
ntsc.composite [composite_border + 5] = 0;
ntsc.composite [composite_border + 6] = i - y;
ntsc.composite [composite_border + 7] = q - y;
out = gen_pixel( &ntsc, 6, 6, out );
ntsc.composite [composite_border + 6] = 0;
ntsc.composite [composite_border + 7] = 0;
/* correct roundoff errors that would cause vertical bands in solid areas */
{
float r = y + i * ntsc.to_rgb [0] + q * ntsc.to_rgb [1];
float g = y + i * ntsc.to_rgb [2] + q * ntsc.to_rgb [3];
float b = y + i * ntsc.to_rgb [4] + q * ntsc.to_rgb [5];
ntsc_rgb_t correct = MAKE_KRGB( (int) r, (int) g, (int) b ) + MAKE_KMASK( 0x100 );
int i;
out = myNTSCEmu->table [entry];
for ( i = 0; i < rgb_kernel_size / 2; i++ )
{
/* sum as would occur when outputting run of pixels using same color,
but don't sum first kernel; the difference between this and the correct
color is what the first kernel's entry should be */
ntsc_rgb_t sum = out [(i+12)%14+14]+out[(i+10)%14+28]+out[(i+8)%14+42]+
out[i+7]+out [ i+ 5 +14]+out[ i+ 3 +28]+out[ i+1 +42];
out [i] = correct - sum;
}
}
}
//FIXME Log_print("atari_ntsc_init(): sharpness:%f saturation:%f brightness:%f contrast:%f gaussian_factor:%f burst_phase:%f, hue:%f gamma_adj:%f saturation_ramp:%f\n",setup->sharpness,setup->saturation,setup->brightness,setup->contrast,setup->gaussian_factor,setup->burst_phase,setup->hue,setup->gamma_adj,setup->saturation_ramp);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::atari_ntsc_blit( unsigned char const* in, long in_pitch,
int width, int height, unsigned short* out, long out_pitch )
{
int const chunk_count = (width - 10) / 7;
long next_in_line = in_pitch - chunk_count * 4;
long next_out_line = out_pitch - (chunk_count + 1) * (7 * sizeof *out);
while ( height-- )
{
#define ENTRY( n ) myNTSCEmu->table [n]
ntsc_rgb_t const* k1 = ENTRY( 0 );
ntsc_rgb_t const* k2 = k1;
ntsc_rgb_t const* k3 = k1;
ntsc_rgb_t const* k4 = k1;
ntsc_rgb_t const* k5 = k4;
ntsc_rgb_t const* k6 = k4;
ntsc_rgb_t const* k7 = k4;
int n;
#if ATARI_NTSC_RGB_BITS == 16
#define TO_RGB( in ) ((in >> 11 & 0xF800) | (in >> 6 & 0x07C0) | (in >> 2 & 0x001F))
#elif ATARI_NTSC_RGB_BITS == 15
#define TO_RGB( in ) ((in >> 12 & 0x7C00) | (in >> 7 & 0x03E0) | (in >> 2 & 0x001F))
#endif
#define PIXEL( a ) {\
ntsc_rgb_t temp =\
k0 [a ] + k1 [(a+5)%7+14] + k2 [(a+3)%7+28] + k3 [(a+1)%7+42] +\
k4 [a+7] + k5 [(a+5)%7+21] + k6 [(a+3)%7+35] + k7 [(a+1)%7+49];\
if ( a ) out [a-1] = rgb;\
CLAMP_RGB( temp, 0 );\
rgb = TO_RGB( temp );\
}
for ( n = chunk_count; n; --n )
{
ntsc_rgb_t const* k0 = ENTRY( in [0] );
int rgb;
PIXEL( 0 );
PIXEL( 1 );
k5 = k1;
k1 = ENTRY( in [1] );
PIXEL( 2 );
PIXEL( 3 );
k6 = k2;
k2 = ENTRY( in [2] );
PIXEL( 4 );
PIXEL( 5 );
k7 = k3;
k3 = ENTRY( in [3] );
PIXEL( 6 );
out [6] = rgb;
k4 = k0;
in += 4;
out += 7;
}
{
ntsc_rgb_t const* k0 = ENTRY( 0 );
int rgb;
PIXEL( 0 );
PIXEL( 1 );
k5 = k1;
k1 = k0;
PIXEL( 2 );
PIXEL( 3 );
k6 = k2;
k2 = k0;
PIXEL( 4 );
PIXEL( 5 );
k7 = k3;
k3 = k0;
PIXEL( 6 );
k4 = k0;
out [6] = rgb;
out += 7;
PIXEL( 0 );
PIXEL( 1 );
k5 = k0;
PIXEL( 2 );
out [2] = rgb;
}
#undef PIXEL
in += next_in_line;
out = (unsigned short*) ((char*) out + next_out_line);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::rotate_matrix( float const* in, float s, float c, float* out )
{
int n = 3;
while ( n-- )
{
float i = *in++;
float q = *in++;
*out++ = i * c - q * s;
*out++ = i * s + q * c;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::ntsc_to_rgb_init( ntsc_to_rgb_t* ntsc, atari_ntsc_setup_t const* setup, float hue )
{
static float const to_rgb [6] = { 0.956, 0.621, -0.272, -0.647, -1.105, 1.702 };
float gaussian_factor = 1+setup->gaussian_factor; /* 1 = normal, > 1 reduces echoes of bright objects (was 2.1)*/
float const brightness_bias = rgb_unit / 128; /* reduces vert bands on artifact colored areas */
int i;
/* ranges need to be scaled a bit to avoid pixels overflowing at extremes */
ntsc->brightness = (setup->brightness-0.0f) * (0.4f * rgb_unit) + brightness_bias;
ntsc->contrast = (setup->contrast-0.0f) * 0.4f + 1;
ntsc->sharpness = 1 + (setup->sharpness < 0 ? setup->sharpness * 0.5f : setup->sharpness);
for ( i = 0; i < composite_size; i++ )
ntsc->composite [i] = 0;
/* Generate gaussian kernel, padded with zero */
for ( i = 0; i < ntsc_kernel_size; i++ )
ntsc->kernel [i] = 0;
for ( i = -composite_border; i <= composite_border; i++ )
ntsc->kernel [ntsc_kernel_size / 2 + i] = exp( i * i * (-0.03125f * gaussian_factor) );
/* normalize kernel totals of every fourth sample (at all four phases) to 0.5, otherwise */
/* i/q low-pass will favor one of the four alignments and cause repeating spots */
for ( i = 0; i < 4; i++ )
{
double sum = 0;
float scale;
int x;
for ( x = i; x < ntsc_kernel_size; x += 4 )
sum += ntsc->kernel [x];
scale = 0.5 / sum;
for ( x = i; x < ntsc_kernel_size; x += 4 )
ntsc->kernel [x] *= scale;
}
/* adjust decoder matrix */
{
float sat = setup->saturation + 1;
rotate_matrix( to_rgb, sin( hue ) * sat, cos( hue ) * sat, ntsc->to_rgb );
}
memset( ntsc->rgb, 0, sizeof ntsc->rgb );
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::ntsc_to_rgb( ntsc_to_rgb_t const* ntsc, int offset, short* out )
{
float const* kernel = &ntsc->kernel [ntsc_kernel_size / 2 - offset];
float f0 = ntsc->composite [offset];
float f1 = ntsc->composite [offset + 1];
float f2 = ntsc->composite [offset + 2];
float f3 = ntsc->composite [offset + 3];
int x = 0;
while ( x < composite_size )
{
#define PIXEL( get_y ) \
{\
float i = kernel [ 0] * f0 + kernel [-2] * f2;\
float q = kernel [-1] * f1 + kernel [-3] * f3;\
float y = get_y;\
float r = y + i * ntsc->to_rgb [0] + q * ntsc->to_rgb [1];\
float g = y + i * ntsc->to_rgb [2] + q * ntsc->to_rgb [3];\
float b = y + i * ntsc->to_rgb [4] + q * ntsc->to_rgb [5];\
kernel++;\
out [0] = (int) r;\
out [1] = (int) g;\
out [2] = (int) b;\
out += 3;\
}
PIXEL( i - ntsc->composite [x + 0] )
PIXEL( q - ntsc->composite [x + 1] )
PIXEL( ntsc->composite [x + 2] - i )
PIXEL( ntsc->composite [x + 3] - q )
x += 4;
#undef PIXEL
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::rescale( short const* in, int count, short* out )
{
do
{
int const accuracy = 16;
int const unit = 1 << accuracy;
int const step = unit / 8;
int left = unit - step;
int right = step;
int n = 7;
while ( n-- )
{
int r = (in [0] * left + in [3] * right) >> accuracy;
int g = (in [1] * left + in [4] * right) >> accuracy;
int b = (in [2] * left + in [5] * right) >> accuracy;
*out++ = r;
*out++ = g;
*out++ = b;
left -= step;
right += step;
in += 3;
}
in += 3;
}
while ( (count -= 7) > 0 );
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::sharpen( short const* in, float level, int count, short* out )
{
/* to do: sharpen luma only? */
int const accuracy = 16;
int const middle = (int) (level * (1 << accuracy));
int const side = (middle - (1 << accuracy)) >> 1;
*out++ = *in++;
*out++ = *in++;
*out++ = *in++;
for ( count = (count - 2) * 3; count--; in++ )
*out++ = (in [0] * middle - in [-3] * side - in [3] * side) >> accuracy;
*out++ = *in++;
*out++ = *in++;
*out++ = *in++;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NTSCFilter::ntsc_rgb_t* NTSCFilter::gen_pixel( ntsc_to_rgb_t* ntsc, int ntsc_pos, int rescaled_pos, ntsc_rgb_t* out )
{
ntsc_to_rgb( ntsc, composite_border + ntsc_pos, ntsc->rgb [rgb_pad] );
rescale( ntsc->rgb [0], rescaled_size, ntsc->rescaled [1] );
sharpen( ntsc->rescaled [1], ntsc->sharpness, rescaled_size, ntsc->rescaled [0] );
{
short const* in = ntsc->rescaled [rescaled_pos];
int n = rgb_kernel_size;
while ( n-- )
{
*out++ = MAKE_KRGB( in [0], in [1], in [2] );
in += 3;
}
}
return out;
}
#if 0 // FIXME - disabled for now
/* added for Atari800, by perrym*/
void ATARI_NTSC_DEFAULTS_Initialise(int *argc, char *argv[], atari_ntsc_setup_t *atari_ntsc_setup)
{
int i, j;
/* Adjust default values here */
atari_ntsc_setup->brightness = -0.1;
atari_ntsc_setup->sharpness = -0.5;
atari_ntsc_setup->saturation = -0.1;
atari_ntsc_setup->gamma_adj = -0.15;
atari_ntsc_setup->burst_phase = -0.60;
atari_ntsc_setup->saturation_ramp = 0.25;
for (i = j = 1; i < *argc; i++) {
if (strcmp(argv[i], "-ntsc_hue") == 0) {
atari_ntsc_setup->hue = atof(argv[++i]);
}else if (strcmp(argv[i], "-ntsc_sat") == 0){
atari_ntsc_setup->saturation = atof(argv[++i]);
}else if (strcmp(argv[i], "-ntsc_cont") == 0){
atari_ntsc_setup->contrast = atof(argv[++i]);
}else if (strcmp(argv[i], "-ntsc_bright") == 0){
atari_ntsc_setup->brightness = atof(argv[++i]);
}else if (strcmp(argv[i], "-ntsc_sharp") == 0){
atari_ntsc_setup->sharpness = atof(argv[++i]);
}else if (strcmp(argv[i], "-ntsc_burst") == 0){
atari_ntsc_setup->burst_phase = atof(argv[++i]);
}else if (strcmp(argv[i], "-ntsc_gauss") == 0){
atari_ntsc_setup->gaussian_factor = atof(argv[++i]);
}else if (strcmp(argv[i], "-ntsc_gamma") == 0){
atari_ntsc_setup->gamma_adj = atof(argv[++i]);
}else if (strcmp(argv[i], "-ntsc_ramp") == 0){
atari_ntsc_setup->saturation_ramp = atof(argv[++i]);
}
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-ntsc_hue <n> Set NTSC hue -1..1 (default %.2g) (-ntsc_emu only)",atari_ntsc_setup->hue);
Log_print("\t-ntsc_sat <n> Set NTSC saturation (default %.2g) (-ntsc_emu only)",atari_ntsc_setup->saturation);
Log_print("\t-ntsc_cont <n> Set NTSC contrast (default %.2g) (-ntsc_emu only)",atari_ntsc_setup->contrast);
Log_print("\t-ntsc_bright <n> Set NTSC brightness (default %.2g) (-ntsc_emu only)",atari_ntsc_setup->brightness);
Log_print("\t-ntsc_sharp <n> Set NTSC sharpness (default %.2g) (-ntsc_emu only)",atari_ntsc_setup->sharpness);
Log_print("\t-ntsc_burst <n> Set NTSC burst phase -1..1 (artif colours)(def: %.2g)",atari_ntsc_setup->burst_phase);
Log_print("\t (-ntsc_emu only)");
Log_print("\t-ntsc_gauss <n> Set NTSC Gaussian factor (default %.2g)",atari_ntsc_setup->gaussian_factor);
Log_print("\t (-ntsc_emu only)");
Log_print("\t-ntsc_gamma <n> Set NTSC gamma adjustment (default %.2g)",atari_ntsc_setup->gamma_adj);
Log_print("\t (-ntsc_emu only)");
Log_print("\t-ntsc_ramp <n> Set NTSC saturation ramp factor (default %.2g)",atari_ntsc_setup->saturation_ramp);
Log_print("\t (-ntsc_emu only)");
}
argv[j++] = argv[i];
}
}
*argc = j;
}
#endif
#endif // DISPLAY_TV

View File

@ -0,0 +1,161 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2012 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifndef NTSC_FILTER_HXX
#define NTSC_FILTER_HXX
#ifdef DISPLAY_TV
#include "bspf.hxx"
#include "Array.hxx"
// Although the blitter supports 15 and 16 bit, we always use 16-bit
#ifndef ATARI_NTSC_RGB_BITS
#define ATARI_NTSC_RGB_BITS 16
#endif
/**
This class is based on the Blargg NTSC filter code from Atari800MacX.
Original code based on implementation from http://www.slack.net/~ant
Based on algorithm by NewRisingSun
License note by Perry: Expat License.
http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses
"This is a simple, permissive non-copyleft free software license, compatible with the GNU GPL."
Atari TIA NTSC composite video to RGB emulator/blitter.
*/
class NTSCFilter
{
public:
NTSCFilter();
virtual ~NTSCFilter();
public:
/**
Cycle through each available NTSC preset mode
@return A message explaining the current NTSC preset mode
*/
const string& next();
/* Blit one or more scanlines of Atari 8-bit palette values to 16-bit 5-6-5 RGB output.
For every 7 output pixels, reads approximately 4 source pixels. Use constants below for
definite input and output pixel counts. */
void atari_ntsc_blit( unsigned char const* atari_in, long in_pitch,
int out_width, int out_height, unsigned short* rgb_out, long out_pitch );
// Atari800 Initialise function by perrym
// void ATARI_NTSC_DEFAULTS_Initialise(int *argc, char *argv[], atari_ntsc_setup_t *atari_ntsc_setup);
private:
/* Picture parameters, ranging from -1.0 to 1.0 where 0.0 is normal. To easily
clear all fields, make it a static object then set whatever fields you want:
static snes_ntsc_setup_t setup;
setup.hue = ...
*/
struct atari_ntsc_setup_t
{
float hue;
float saturation;
float contrast;
float brightness;
float sharpness;
float burst_phase; // not in radians; -1.0 = -180 degrees, 1.0 = +180 degrees
float gaussian_factor;
float gamma_adj; // gamma adjustment
float saturation_ramp; // lower saturation for higher luma values
};
enum {
atari_ntsc_entry_size = 56,
atari_ntsc_color_count = 256,
// Useful values to use for output width and number of input pixels read
atari_ntsc_min_out_width = 570, // minimum width that doesn't cut off active area
atari_ntsc_min_in_width = 320,
atari_ntsc_full_out_width = 598, // room for 8-pixel left & right overscan borders
atari_ntsc_full_in_width = 336,
// Originally present in .c file
composite_border = 6,
center_offset = 1,
alignment_count = 4, // different pixel alignments with respect to yiq quads */
rgb_kernel_size = atari_ntsc_entry_size / alignment_count,
// Originally present in .c file
composite_size = composite_border + 8 + composite_border,
rgb_pad = (center_offset + composite_border + 7) / 8 * 8 - center_offset - composite_border,
rgb_size = (rgb_pad + composite_size + 7) / 8 * 8,
rescaled_size = rgb_size / 8 * 7,
ntsc_kernel_size = composite_size * 2
};
typedef uInt32 ntsc_rgb_t;
// Caller must allocate space for blitter data, which uses 56 KB of memory.
struct atari_ntsc_t
{
ntsc_rgb_t table [atari_ntsc_color_count] [atari_ntsc_entry_size];
};
// Originall present in .c file
struct ntsc_to_rgb_t
{
float composite [composite_size];
float to_rgb [6];
float brightness;
float contrast;
float sharpness;
short rgb [rgb_size] [3];
short rescaled [rescaled_size + 1] [3]; /* extra space for sharpen */
float kernel [ntsc_kernel_size];
};
atari_ntsc_t* myNTSCEmu;
int myCurrentModeNum;
Common::Array<atari_ntsc_setup_t> myModeList;
private:
/* Initialize and adjust parameters. Can be called multiple times on the same
atari_ntsc_t object. */
void atari_ntsc_init( atari_ntsc_setup_t const* setup );
static void rotate_matrix( float const* in, float s, float c, float* out );
static void ntsc_to_rgb_init( ntsc_to_rgb_t* ntsc, atari_ntsc_setup_t const* setup, float hue );
/* Convert NTSC composite signal to RGB, where composite signal contains
only four non-zero samples beginning at offset */
static void ntsc_to_rgb( ntsc_to_rgb_t const* ntsc, int offset, short* out );
/* Rescale pixels to NTSC aspect ratio using linear interpolation,
with 7 output pixels for every 8 input pixels, linear interpolation */
static void rescale( short const* in, int count, short* out );
/* Sharpen image using (level-1)/2, level, (level-1)/2 convolution kernel */
static void sharpen( short const* in, float level, int count, short* out );
/* Generate pixel and capture into table */
static ntsc_rgb_t* gen_pixel( ntsc_to_rgb_t* ntsc, int ntsc_pos, int rescaled_pos, ntsc_rgb_t* out );
};
#endif // DISPLAY_TV
#endif

View File

@ -0,0 +1,10 @@
MODULE := src/common/tv_filters
MODULE_OBJS := \
src/common/tv_filters/NTSCFilter.o
MODULE_DIRS += \
src/common/tv_filters
# Include common rules
include $(srcdir)/common.rules