mirror of
https://github.com/cmosher01/Epple-II.git
synced 2024-12-22 14:29:35 +00:00
TV: improve color calculation algorithm
This commit is contained in:
parent
06fc2e6bce
commit
0313881ac0
@ -396,12 +396,12 @@ CB AnalogTV::get_cb(int lineno)
|
||||
|
||||
static std::map<CB,IQ> cacheCB;
|
||||
|
||||
const double AnalogTV::IQ_OFFSET_DEGREES = 33;
|
||||
const double AnalogTV::IQ_OFFSET_DEGREES = 33; //NTSC spec. 33 IQ is rotated 33 degrees
|
||||
const double AnalogTV::IQ_OFFSET_RADIANS = AnalogTV::IQ_OFFSET_DEGREES * 3.1415927 / 180;
|
||||
const double AnalogTV::TINT_I = -cos(AnalogTV::IQ_OFFSET_RADIANS);
|
||||
const double AnalogTV::TINT_Q = +sin(AnalogTV::IQ_OFFSET_RADIANS);
|
||||
|
||||
const double AnalogTV::COLOR_THRESH(1.4);
|
||||
const double AnalogTV::COLOR_THRESH(sqrt(2));
|
||||
|
||||
IQ AnalogTV::get_iq_factor(const CB& cb)
|
||||
{
|
||||
@ -440,20 +440,14 @@ const int AnalogTV::IQINTOFF(130);
|
||||
|
||||
void AnalogTV::ntsc_to_yiq(const int isignal, const int siglen, const IQ& iq_factor, int yiq[]) {
|
||||
FilterLuma filterY;
|
||||
FilterChroma filterI;
|
||||
FilterChroma filterQ;
|
||||
FilterChromaI filterI;
|
||||
FilterChromaQ filterQ;
|
||||
for (int off = 0; off < siglen; ++off) {
|
||||
const int sig = this->signal[isignal + off];
|
||||
|
||||
const int y = filterY.next(sig);
|
||||
int i;
|
||||
int q;
|
||||
if (y < -2) {
|
||||
i = 0;
|
||||
q = 0;
|
||||
} else {
|
||||
i = filterI.next(sig * iq_factor.get(off & 3));
|
||||
q = filterQ.next(sig * iq_factor.get((off + 3) & 3));
|
||||
}
|
||||
const int i = filterI.next(sig) * iq_factor.get(off & 3);
|
||||
const int q = filterQ.next(sig) * iq_factor.get((off + 3) & 3);
|
||||
|
||||
yiq[off] = (((q+IQINTOFF)&0xff) << 16) | (((i+IQINTOFF)&0xff) << 8) | ((y+IQINTOFF)&0xff);
|
||||
}
|
||||
|
@ -19,25 +19,58 @@
|
||||
|
||||
/*
|
||||
Generated by the utility at http://www-users.cs.york.ac.uk/~fisher/mkfilter
|
||||
3rd order low-pass Butterworth filter at 1500000 Hz.
|
||||
(sample rate 14318182 Hz)
|
||||
2nd order band-pass Butterworth filters (sample rate 14318182 Hz)
|
||||
*/
|
||||
#define GAIN 4.910093226e+01
|
||||
|
||||
FilterChroma::FilterChroma() {
|
||||
xv[0]=xv[1]=xv[2]=xv[3]=0;
|
||||
yv[0]=yv[1]=yv[2]=yv[3]=0;
|
||||
|
||||
|
||||
/*
|
||||
pass 2079545 Hz through 5079545 Hz.
|
||||
*/
|
||||
|
||||
#define GAINI 4.501156488e+00
|
||||
|
||||
FilterChromaI::FilterChromaI() {
|
||||
xv[0]=xv[1]=xv[2]=xv[3]=xv[4]=0;
|
||||
yv[0]=yv[1]=yv[2]=yv[3]=yv[4]=0;
|
||||
}
|
||||
|
||||
FilterChroma::~FilterChroma() {
|
||||
FilterChromaI::~FilterChromaI() {
|
||||
}
|
||||
|
||||
double FilterChroma::next(const double v) {
|
||||
xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3];
|
||||
xv[3] = v / GAIN;
|
||||
yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3];
|
||||
yv[3] = (xv[0] + xv[3]) + 3 * (xv[1] + xv[2])
|
||||
+ ( 0.2608994296 * yv[0]) + ( -1.1262209208 * yv[1])
|
||||
+ ( 1.7023917944 * yv[2]);
|
||||
return yv[3];
|
||||
double FilterChromaI::next(const double v) {
|
||||
xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4];
|
||||
xv[4] = v / GAINI;
|
||||
yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4];
|
||||
yv[4] = (xv[0] + xv[4]) - 2 * xv[2]
|
||||
+ ( -0.1873928488 * yv[0]) + ( 0.0000001868 * yv[1])
|
||||
+ ( -0.2987323434 * yv[2]) + ( 0.0000006376 * yv[3]);
|
||||
return yv[4];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
pass 2979545 Hz through 4179545 Hz.
|
||||
*/
|
||||
|
||||
#define GAINQ 2.000943914e+01
|
||||
|
||||
FilterChromaQ::FilterChromaQ() {
|
||||
xv[0]=xv[1]=xv[2]=xv[3]=xv[4]=0;
|
||||
yv[0]=yv[1]=yv[2]=yv[3]=yv[4]=0;
|
||||
}
|
||||
|
||||
FilterChromaQ::~FilterChromaQ() {
|
||||
}
|
||||
|
||||
double FilterChromaQ::next(const double v) {
|
||||
xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4];
|
||||
xv[4] = v / GAINQ;
|
||||
yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4];
|
||||
yv[4] = (xv[0] + xv[4]) - 2 * xv[2]
|
||||
+ ( -0.4755965671 * yv[0]) + ( 0.0000005060 * yv[1])
|
||||
+ ( -1.2756909139 * yv[2]) + ( 0.0000007444 * yv[3]);
|
||||
return yv[4];
|
||||
}
|
||||
|
@ -18,14 +18,25 @@
|
||||
#ifndef FILTERCHROMA
|
||||
#define FILTERCHROMA
|
||||
|
||||
class FilterChroma {
|
||||
class FilterChromaI {
|
||||
private:
|
||||
double xv[4];
|
||||
double yv[4];
|
||||
double xv[5];
|
||||
double yv[5];
|
||||
|
||||
public:
|
||||
FilterChroma();
|
||||
~FilterChroma();
|
||||
FilterChromaI();
|
||||
~FilterChromaI();
|
||||
double next(const double v);
|
||||
};
|
||||
|
||||
class FilterChromaQ {
|
||||
private:
|
||||
double xv[5];
|
||||
double yv[5];
|
||||
|
||||
public:
|
||||
FilterChromaQ();
|
||||
~FilterChromaQ();
|
||||
double next(const double v);
|
||||
};
|
||||
|
||||
|
@ -19,14 +19,14 @@
|
||||
|
||||
/*
|
||||
Generated by the utility at http://www-users.cs.york.ac.uk/~fisher/mkfilter
|
||||
3rd order low-pass Butterworth filter at 4500000 Hz with extra zero at 3500000 Hz.
|
||||
1st order low-pass Butterworth filter at 2079545 Hz with extra zero at 3579545 Hz
|
||||
(sample rate 14318182 Hz)
|
||||
*/
|
||||
|
||||
#define GAIN 6.715664173
|
||||
#define GAIN 6.074790079e+00
|
||||
|
||||
FilterLuma::FilterLuma() {
|
||||
xv[0]=xv[1]=xv[2]=xv[3]=xv[4]=xv[5]=0;
|
||||
xv[0]=xv[1]=xv[2]=xv[3]=0;
|
||||
yv[0]=yv[1]=yv[2]=yv[3]=0;
|
||||
}
|
||||
|
||||
@ -34,11 +34,10 @@ FilterLuma::~FilterLuma() {
|
||||
}
|
||||
|
||||
double FilterLuma::next(const double v) {
|
||||
xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5];
|
||||
xv[5] = v / GAIN;
|
||||
xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3];
|
||||
xv[3] = v / GAIN;
|
||||
yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3];
|
||||
yv[3] = (xv[0] + xv[5]) + 2.9302009676 * (xv[1] + xv[4]) + 3.7906029028 * (xv[2] + xv[3])
|
||||
+ ( -0.0757751449 * yv[0]) + ( -0.4803383261 * yv[1])
|
||||
+ ( -0.7432283875 * yv[2]);
|
||||
yv[3] = (xv[0] + xv[3]) + 0.9999995612 * (xv[1] + xv[2])
|
||||
+ ( 0.3415411775 * yv[2]);
|
||||
return yv[3];
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
class FilterLuma {
|
||||
private:
|
||||
double xv[6];
|
||||
double xv[4];
|
||||
double yv[4];
|
||||
|
||||
public:
|
||||
|
@ -294,12 +294,8 @@ signed char inline PictureGenerator::vbl(const int hcycle)
|
||||
// Note that this color burst signal only affects "old TV" mode;
|
||||
// the other color modes use A2ColorsObserved.
|
||||
const signed char PictureGenerator::lutCB[] =
|
||||
{
|
||||
0,
|
||||
-AppleNTSC::CB_LEVEL,
|
||||
0,
|
||||
+AppleNTSC::CB_LEVEL,
|
||||
};
|
||||
{ 0, -AppleNTSC::CB_LEVEL, 0, +AppleNTSC::CB_LEVEL };
|
||||
//{ +AppleNTSC::CB_LEVEL/2, -AppleNTSC::CB_LEVEL/2, -AppleNTSC::CB_LEVEL/2, +AppleNTSC::CB_LEVEL/2 };
|
||||
|
||||
signed char inline PictureGenerator::hbl(const int hcycle)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user