diff --git a/src/analogtv.cpp b/src/analogtv.cpp index 5614772..451372c 100644 --- a/src/analogtv.cpp +++ b/src/analogtv.cpp @@ -396,12 +396,12 @@ CB AnalogTV::get_cb(int lineno) static std::map 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); } diff --git a/src/filterchroma.cpp b/src/filterchroma.cpp index 0e45703..3ab4d2d 100644 --- a/src/filterchroma.cpp +++ b/src/filterchroma.cpp @@ -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]; } diff --git a/src/filterchroma.h b/src/filterchroma.h index c29858b..4db7e34 100644 --- a/src/filterchroma.h +++ b/src/filterchroma.h @@ -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); }; diff --git a/src/filterluma.cpp b/src/filterluma.cpp index de52cdc..3d4115f 100644 --- a/src/filterluma.cpp +++ b/src/filterluma.cpp @@ -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]; } diff --git a/src/filterluma.h b/src/filterluma.h index 30ae653..829cba9 100644 --- a/src/filterluma.h +++ b/src/filterluma.h @@ -20,7 +20,7 @@ class FilterLuma { private: - double xv[6]; + double xv[4]; double yv[4]; public: diff --git a/src/picturegenerator.cpp b/src/picturegenerator.cpp index f4443d4..8cc55e5 100644 --- a/src/picturegenerator.cpp +++ b/src/picturegenerator.cpp @@ -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) {