mirror of
https://github.com/dyne/frei0r.git
synced 2025-12-05 22:29:59 +01:00
Merge branch 'master' into master
This commit is contained in:
@@ -557,6 +557,10 @@ position pointOnBezier(double t, position points[4])
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
# define strtok_r strtok_s
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits given string into sub-strings at given delimiter.
|
* Splits given string into sub-strings at given delimiter.
|
||||||
* \param string input string
|
* \param string input string
|
||||||
@@ -569,11 +573,11 @@ int tokenise(char *string, const char *delimiter, char ***tokens)
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
char *input = strdup(string);
|
char *input = strdup(string);
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
result = strtok(input, delimiter);
|
result = strtok_r(string, delimiter, &input);
|
||||||
while (result != NULL) {
|
while (result != NULL) {
|
||||||
*tokens = realloc(*tokens, (count + 1) * sizeof(char *));
|
*tokens = realloc(*tokens, (count + 1) * sizeof(char *));
|
||||||
(*tokens)[count++] = strdup(result);
|
(*tokens)[count++] = strdup(result);
|
||||||
result = strtok(NULL, delimiter);
|
result = strtok_r(NULL, delimiter, &input);
|
||||||
}
|
}
|
||||||
free(input);
|
free(input);
|
||||||
return count;
|
return count;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Copyright (C) 2010 Marko Cebokli http://lea.hamradio.si/~s57uuu
|
|||||||
double PI=3.14159265358979;
|
double PI=3.14159265358979;
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
void draw_rectangle(float_rgba *s, int w, int h, float x, float y, float wr, float hr, float_rgba c)
|
static inline void draw_rectangle(float_rgba *s, int w, int h, float x, float y, float wr, float hr, float_rgba c)
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
int zx,kx,zy,ky;
|
int zx,kx,zy,ky;
|
||||||
@@ -139,7 +139,7 @@ draw_rectangle(s, w, h, x1, y1+1, v, 1, black);
|
|||||||
//justified
|
//justified
|
||||||
//p=0 one decimal place p=1 three decimal places
|
//p=0 one decimal place p=1 three decimal places
|
||||||
//m=1 always show sign
|
//m=1 always show sign
|
||||||
void forstr(float a, int p, int m, char *s)
|
inline static void forstr(float a, int p, int m, char *s)
|
||||||
{
|
{
|
||||||
float b;
|
float b;
|
||||||
char *p3=" %5.3f";
|
char *p3=" %5.3f";
|
||||||
@@ -192,14 +192,14 @@ if (mm==1)
|
|||||||
forstr(s.rms,1-u,0,rs);
|
forstr(s.rms,1-u,0,rs);
|
||||||
forstr(s.min,1-u,m,ns);
|
forstr(s.min,1-u,m,ns);
|
||||||
forstr(s.max,1-u,m,xs);
|
forstr(s.max,1-u,m,xs);
|
||||||
sprintf(fs,"%s%s%s %s%s", lab, as, rs, ns, xs);
|
snprintf(fs,255,"%s%s%s %s%s", lab, as, rs, ns, xs);
|
||||||
sprintf(str,fs,s.avg,s.rms,s.min,s.max);
|
sprintf(str,fs,s.avg,s.rms,s.min,s.max);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
forstr(s.avg,1-u,m,as);
|
forstr(s.avg,1-u,m,as);
|
||||||
forstr(s.rms,1-u,0,rs);
|
forstr(s.rms,1-u,0,rs);
|
||||||
sprintf(fs,"%s%s%s", lab, as, rs);
|
snprintf(fs,255,"%s%s%s", lab, as, rs);
|
||||||
sprintf(str,fs,s.avg,s.rms);
|
sprintf(str,fs,s.avg,s.rms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -745,4 +745,3 @@ crosshair(in->sl, in->w, in->h, in->x, in->y, 2*in->sx+1, 2*in->sy+1, 15);
|
|||||||
|
|
||||||
floatrgba2color(in->sl, outframe, in->w , in->h);
|
floatrgba2color(in->sl, outframe, in->w , in->h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ while (c[i]!=0)
|
|||||||
//justified
|
//justified
|
||||||
//p=0 one decimal place p=1 three decimal places
|
//p=0 one decimal place p=1 three decimal places
|
||||||
//m=1 always show sign
|
//m=1 always show sign
|
||||||
void forstr(float a, int p, int m, char *s)
|
inline static void forstr(float a, int p, int m, char *s)
|
||||||
{
|
{
|
||||||
float b;
|
float b;
|
||||||
char *p3=" %5.3f";
|
char *p3=" %5.3f";
|
||||||
@@ -320,7 +320,7 @@ if ((dit&0x00000001)!=0) //marker 1 value
|
|||||||
if (m1>0)
|
if (m1>0)
|
||||||
{
|
{
|
||||||
forstr(data[0],1-u,0,frs);
|
forstr(data[0],1-u,0,frs);
|
||||||
sprintf(fs,"%%s Mk1=%s", frs);
|
snprintf(fs,255,"%%s Mk1=%s", frs);
|
||||||
sprintf(str,fs,str,data[0]);
|
sprintf(str,fs,str,data[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -331,7 +331,7 @@ if ((dit&0x00000004)!=0) //marker 2 value
|
|||||||
if (m2>0)
|
if (m2>0)
|
||||||
{
|
{
|
||||||
forstr(data[1],1-u,0,frs);
|
forstr(data[1],1-u,0,frs);
|
||||||
sprintf(fs,"%%s Mk2=%s", frs);
|
snprintf(fs,255,"%%s Mk2=%s", frs);
|
||||||
sprintf(str,fs,str,data[1]);
|
sprintf(str,fs,str,data[1]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -342,7 +342,7 @@ if ((dit&0x00000010)!=0) //difference marker2-marker1
|
|||||||
if ((m2>0)&&(m1>0))
|
if ((m2>0)&&(m1>0))
|
||||||
{
|
{
|
||||||
forstr(data[2],1-u,0,frs);
|
forstr(data[2],1-u,0,frs);
|
||||||
sprintf(fs,"%%s D=%s", frs);
|
snprintf(fs,255,"%%s D=%s", frs);
|
||||||
sprintf(str,fs,str,data[2]);
|
sprintf(str,fs,str,data[2]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -351,25 +351,25 @@ if ((dit&0x00000010)!=0) //difference marker2-marker1
|
|||||||
if ((dit&0x00000020)!=0) //average of profile
|
if ((dit&0x00000020)!=0) //average of profile
|
||||||
{
|
{
|
||||||
forstr(data[3],1-u,0,frs);
|
forstr(data[3],1-u,0,frs);
|
||||||
sprintf(fs,"%%s Avg=%s", frs);
|
snprintf(fs,255,"%%s Avg=%s", frs);
|
||||||
sprintf(str,fs,str,data[3]);
|
sprintf(str,fs,str,data[3]);
|
||||||
}
|
}
|
||||||
if ((dit&0x00000040)!=0) //RMS of profile
|
if ((dit&0x00000040)!=0) //RMS of profile
|
||||||
{
|
{
|
||||||
forstr(data[4],1-u,0,frs);
|
forstr(data[4],1-u,0,frs);
|
||||||
sprintf(fs,"%%s RMS=%s", frs);
|
snprintf(fs,255,"%%s RMS=%s", frs);
|
||||||
sprintf(str,fs,str,data[4]);
|
sprintf(str,fs,str,data[4]);
|
||||||
}
|
}
|
||||||
if ((dit&0x00000080)!=0) //MIN of profile
|
if ((dit&0x00000080)!=0) //MIN of profile
|
||||||
{
|
{
|
||||||
forstr(data[5],1-u,0,frs);
|
forstr(data[5],1-u,0,frs);
|
||||||
sprintf(fs,"%%s Min=%s", frs);
|
snprintf(fs,255,"%%s Min=%s", frs);
|
||||||
sprintf(str,fs,str,data[5]);
|
sprintf(str,fs,str,data[5]);
|
||||||
}
|
}
|
||||||
if ((dit&0x00000100)!=0) //MAX of profile
|
if ((dit&0x00000100)!=0) //MAX of profile
|
||||||
{
|
{
|
||||||
forstr(data[6],1-u,0,frs);
|
forstr(data[6],1-u,0,frs);
|
||||||
sprintf(fs,"%%s Max=%s", frs);
|
snprintf(fs,255,"%%s Max=%s", frs);
|
||||||
sprintf(str,fs,str,data[6]);
|
sprintf(str,fs,str,data[6]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1035,4 +1035,3 @@ prof(in->sl, in->w, in->h, &in->poz, in->x, in->y, in->tilt, in->len, 1, in->mer
|
|||||||
|
|
||||||
floatrgba2color(in->sl, outframe, in->w , in->h);
|
floatrgba2color(in->sl, outframe, in->w , in->h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,23 @@ crt_sincos14(int *s, int *c, int n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int
|
||||||
|
crt_bpp4fmt(int format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case CRT_PIX_FORMAT_RGB:
|
||||||
|
case CRT_PIX_FORMAT_BGR:
|
||||||
|
return 3;
|
||||||
|
case CRT_PIX_FORMAT_ARGB:
|
||||||
|
case CRT_PIX_FORMAT_RGBA:
|
||||||
|
case CRT_PIX_FORMAT_ABGR:
|
||||||
|
case CRT_PIX_FORMAT_BGRA:
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/********************************* FILTERS ***********************************/
|
/********************************* FILTERS ***********************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -222,10 +239,11 @@ eqf(struct EQF *f, int s)
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
crt_resize(struct CRT *v, int w, int h, unsigned char *out)
|
crt_resize(struct CRT *v, int w, int h, int f, unsigned char *out)
|
||||||
{
|
{
|
||||||
v->outw = w;
|
v->outw = w;
|
||||||
v->outh = h;
|
v->outh = h;
|
||||||
|
v->out_format = f;
|
||||||
v->out = out;
|
v->out = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,21 +258,13 @@ crt_reset(struct CRT *v)
|
|||||||
v->white_point = 100;
|
v->white_point = 100;
|
||||||
v->hsync = 0;
|
v->hsync = 0;
|
||||||
v->vsync = 0;
|
v->vsync = 0;
|
||||||
|
|
||||||
v->scanlines = 0; /* leave gaps between lines if necessary */
|
|
||||||
v->blend = 0; /* blend new field onto previous image */
|
|
||||||
|
|
||||||
// these options were previously #defined in crt_core.h
|
|
||||||
v->crt_do_vsync = 1;
|
|
||||||
v->crt_do_hsync = 1;
|
|
||||||
v->do_vhs_noise = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
crt_init(struct CRT *v, int w, int h, unsigned char *out)
|
crt_init(struct CRT *v, int w, int h, int f, unsigned char *out)
|
||||||
{
|
{
|
||||||
memset(v, 0, sizeof(struct CRT));
|
memset(v, 0, sizeof(struct CRT));
|
||||||
crt_resize(v, w, h, out);
|
crt_resize(v, w, h, f, out);
|
||||||
crt_reset(v);
|
crt_reset(v);
|
||||||
v->rn = 194;
|
v->rn = 194;
|
||||||
|
|
||||||
@@ -293,17 +303,24 @@ crt_demodulate(struct CRT *v, int noise)
|
|||||||
int huesn, huecs;
|
int huesn, huecs;
|
||||||
int xnudge = -3, ynudge = 3;
|
int xnudge = -3, ynudge = 3;
|
||||||
int bright = v->brightness - (BLACK_LEVEL + v->black_point);
|
int bright = v->brightness - (BLACK_LEVEL + v->black_point);
|
||||||
int pitch;
|
int bpp, pitch;
|
||||||
|
#if CRT_DO_BLOOM
|
||||||
|
int prev_e; /* filtered beam energy per scan line */
|
||||||
|
int max_e; /* approx maximum energy in a scan line */
|
||||||
|
#endif
|
||||||
|
|
||||||
pitch = v->outw * BPP;
|
bpp = crt_bpp4fmt(v->out_format);
|
||||||
|
if (bpp == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pitch = v->outw * bpp;
|
||||||
|
|
||||||
crt_sincos14(&huesn, &huecs, ((v->hue % 360) + 33) * 8192 / 180);
|
crt_sincos14(&huesn, &huecs, ((v->hue % 360) + 33) * 8192 / 180);
|
||||||
huesn >>= 11; /* make 4-bit */
|
huesn >>= 11; /* make 4-bit */
|
||||||
huecs >>= 11;
|
huecs >>= 11;
|
||||||
|
|
||||||
rn = v->rn;
|
rn = v->rn;
|
||||||
if(!v->crt_do_vsync)
|
#if !CRT_DO_VSYNC
|
||||||
{
|
|
||||||
/* determine field before we add noise,
|
/* determine field before we add noise,
|
||||||
* otherwise it's not reliably recoverable
|
* otherwise it's not reliably recoverable
|
||||||
*/
|
*/
|
||||||
@@ -318,19 +335,17 @@ crt_demodulate(struct CRT *v, int noise)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
found_field:
|
found_field:
|
||||||
/* if vsync signal was in second half of line, odd field */
|
/* if vsync signal was in second half of line, odd field */
|
||||||
field = (j > (CRT_HRES / 2));
|
field = (j > (CRT_HRES / 2));
|
||||||
v->vsync = -3;
|
v->vsync = -3;
|
||||||
}
|
#endif
|
||||||
if(v->do_vhs_noise)
|
#if ((CRT_SYSTEM == CRT_SYSTEM_NTSCVHS) && CRT_VHS_NOISE)
|
||||||
{
|
|
||||||
line = ((rand() % 8) - 4) + 14;
|
line = ((rand() % 8) - 4) + 14;
|
||||||
}
|
#endif
|
||||||
for (i = 0; i < CRT_INPUT_SIZE; i++) {
|
for (i = 0; i < CRT_INPUT_SIZE; i++) {
|
||||||
int nn = noise;
|
int nn = noise;
|
||||||
if(v->do_vhs_noise)
|
#if ((CRT_SYSTEM == CRT_SYSTEM_NTSCVHS) && CRT_VHS_NOISE)
|
||||||
{
|
|
||||||
rn = rand();
|
rn = rand();
|
||||||
if (i > (CRT_INPUT_SIZE - CRT_HRES * (16 + ((rand() % 20) - 10))) &&
|
if (i > (CRT_INPUT_SIZE - CRT_HRES * (16 + ((rand() % 20) - 10))) &&
|
||||||
i < (CRT_INPUT_SIZE - CRT_HRES * (5 + ((rand() % 8) - 4)))) {
|
i < (CRT_INPUT_SIZE - CRT_HRES * (5 + ((rand() % 8) - 4)))) {
|
||||||
@@ -340,11 +355,9 @@ crt_demodulate(struct CRT *v, int noise)
|
|||||||
crt_sincos14(&sn, &cs, ln * 8192 / 180);
|
crt_sincos14(&sn, &cs, ln * 8192 / 180);
|
||||||
nn = cs >> 8;
|
nn = cs >> 8;
|
||||||
}
|
}
|
||||||
}
|
#else
|
||||||
else
|
|
||||||
{
|
|
||||||
rn = (214019 * rn + 140327895);
|
rn = (214019 * rn + 140327895);
|
||||||
}
|
#endif
|
||||||
/* signal + noise */
|
/* signal + noise */
|
||||||
s = v->analog[i] + (((((rn >> 16) & 0xff) - 0x7f) * nn) >> 8);
|
s = v->analog[i] + (((((rn >> 16) & 0xff) - 0x7f) * nn) >> 8);
|
||||||
if (s > 127) { s = 127; }
|
if (s > 127) { s = 127; }
|
||||||
@@ -353,8 +366,7 @@ crt_demodulate(struct CRT *v, int noise)
|
|||||||
}
|
}
|
||||||
v->rn = rn;
|
v->rn = rn;
|
||||||
|
|
||||||
if(v->crt_do_vsync)
|
#if CRT_DO_VSYNC
|
||||||
{
|
|
||||||
/* Look for vertical sync.
|
/* Look for vertical sync.
|
||||||
*
|
*
|
||||||
* This is done by integrating the signal and
|
* This is done by integrating the signal and
|
||||||
@@ -378,12 +390,16 @@ crt_demodulate(struct CRT *v, int noise)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vsync_found:
|
vsync_found:
|
||||||
v->vsync = line; /* vsync found (or gave up) at this line */
|
v->vsync = line; /* vsync found (or gave up) at this line */
|
||||||
/* if vsync signal was in second half of line, odd field */
|
/* if vsync signal was in second half of line, odd field */
|
||||||
field = (j > (CRT_HRES / 2));
|
field = (j > (CRT_HRES / 2));
|
||||||
}
|
#endif
|
||||||
|
|
||||||
|
#if CRT_DO_BLOOM
|
||||||
|
max_e = (128 + (noise / 2)) * AV_LEN;
|
||||||
|
prev_e = (16384 / 8);
|
||||||
|
#endif
|
||||||
/* ratio of output height to active video lines in the signal */
|
/* ratio of output height to active video lines in the signal */
|
||||||
ratio = (v->outh << 16) / CRT_LINES;
|
ratio = (v->outh << 16) / CRT_LINES;
|
||||||
ratio = (ratio + 32768) >> 16;
|
ratio = (ratio + 32768) >> 16;
|
||||||
@@ -405,6 +421,9 @@ crt_demodulate(struct CRT *v, int noise)
|
|||||||
int xpos, ypos;
|
int xpos, ypos;
|
||||||
int beg, end;
|
int beg, end;
|
||||||
int phasealign;
|
int phasealign;
|
||||||
|
#if CRT_DO_BLOOM
|
||||||
|
int line_w;
|
||||||
|
#endif
|
||||||
|
|
||||||
beg = (line - CRT_TOP + 0) * (v->outh + v->v_fac) / CRT_LINES + field;
|
beg = (line - CRT_TOP + 0) * (v->outh + v->v_fac) / CRT_LINES + field;
|
||||||
end = (line - CRT_TOP + 1) * (v->outh + v->v_fac) / CRT_LINES + field;
|
end = (line - CRT_TOP + 1) * (v->outh + v->v_fac) / CRT_LINES + field;
|
||||||
@@ -424,14 +443,11 @@ crt_demodulate(struct CRT *v, int noise)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(v->crt_do_hsync)
|
#if CRT_DO_HSYNC
|
||||||
{
|
|
||||||
v->hsync = POSMOD(i + v->hsync, CRT_HRES);
|
v->hsync = POSMOD(i + v->hsync, CRT_HRES);
|
||||||
}
|
#else
|
||||||
else
|
|
||||||
{
|
|
||||||
v->hsync = 0;
|
v->hsync = 0;
|
||||||
}
|
#endif
|
||||||
|
|
||||||
xpos = POSMOD(AV_BEG + v->hsync + xnudge, CRT_HRES);
|
xpos = POSMOD(AV_BEG + v->hsync + xnudge, CRT_HRES);
|
||||||
ypos = POSMOD(line + v->vsync + ynudge, CRT_VRES);
|
ypos = POSMOD(line + v->vsync + ynudge, CRT_VRES);
|
||||||
@@ -493,13 +509,28 @@ crt_demodulate(struct CRT *v, int noise)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sig = v->inp + pos;
|
sig = v->inp + pos;
|
||||||
|
#if CRT_DO_BLOOM
|
||||||
|
s = 0;
|
||||||
|
for (i = 0; i < AV_LEN; i++) {
|
||||||
|
s += sig[i]; /* sum up the scan line */
|
||||||
|
}
|
||||||
|
/* bloom emulation */
|
||||||
|
prev_e = (prev_e * 123 / 128) + ((((max_e >> 1) - s) << 10) / max_e);
|
||||||
|
line_w = (AV_LEN * 112 / 128) + (prev_e >> 9);
|
||||||
|
|
||||||
|
dx = (line_w << 12) / v->outw;
|
||||||
|
scanL = ((AV_LEN / 2) - (line_w >> 1) + 8) << 12;
|
||||||
|
scanR = (AV_LEN - 1) << 12;
|
||||||
|
|
||||||
|
L = (scanL >> 12);
|
||||||
|
R = (scanR >> 12);
|
||||||
|
#else
|
||||||
dx = ((AV_LEN - 1) << 12) / v->outw;
|
dx = ((AV_LEN - 1) << 12) / v->outw;
|
||||||
scanL = 0;
|
scanL = 0;
|
||||||
scanR = (AV_LEN - 1) << 12;
|
scanR = (AV_LEN - 1) << 12;
|
||||||
L = 0;
|
L = 0;
|
||||||
R = AV_LEN;
|
R = AV_LEN;
|
||||||
|
#endif
|
||||||
reset_eq(&eqY);
|
reset_eq(&eqY);
|
||||||
reset_eq(&eqI);
|
reset_eq(&eqI);
|
||||||
reset_eq(&eqQ);
|
reset_eq(&eqQ);
|
||||||
@@ -552,8 +583,26 @@ crt_demodulate(struct CRT *v, int noise)
|
|||||||
|
|
||||||
if (v->blend) {
|
if (v->blend) {
|
||||||
aa = (r << 16 | g << 8 | b);
|
aa = (r << 16 | g << 8 | b);
|
||||||
bb = cL[0] << 16 | cL[1] << 8 | cL[2];
|
|
||||||
|
|
||||||
|
switch (v->out_format) {
|
||||||
|
case CRT_PIX_FORMAT_RGB:
|
||||||
|
case CRT_PIX_FORMAT_RGBA:
|
||||||
|
bb = cL[0] << 16 | cL[1] << 8 | cL[2];
|
||||||
|
break;
|
||||||
|
case CRT_PIX_FORMAT_BGR:
|
||||||
|
case CRT_PIX_FORMAT_BGRA:
|
||||||
|
bb = cL[2] << 16 | cL[1] << 8 | cL[0];
|
||||||
|
break;
|
||||||
|
case CRT_PIX_FORMAT_ARGB:
|
||||||
|
bb = cL[1] << 16 | cL[2] << 8 | cL[3];
|
||||||
|
break;
|
||||||
|
case CRT_PIX_FORMAT_ABGR:
|
||||||
|
bb = cL[3] << 16 | cL[2] << 8 | cL[1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bb = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* blend with previous color there */
|
/* blend with previous color there */
|
||||||
bb = (((aa & 0xfefeff) >> 1) + ((bb & 0xfefeff) >> 1));
|
bb = (((aa & 0xfefeff) >> 1) + ((bb & 0xfefeff) >> 1));
|
||||||
@@ -561,12 +610,52 @@ crt_demodulate(struct CRT *v, int noise)
|
|||||||
bb = (r << 16 | g << 8 | b);
|
bb = (r << 16 | g << 8 | b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (v->out_format) {
|
||||||
|
case CRT_PIX_FORMAT_RGB:
|
||||||
|
cL[0] = bb >> 16 & 0xff;
|
||||||
|
cL[1] = bb >> 8 & 0xff;
|
||||||
|
cL[2] = bb >> 0 & 0xff;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CRT_PIX_FORMAT_RGBA:
|
||||||
cL[0] = bb >> 16 & 0xff;
|
cL[0] = bb >> 16 & 0xff;
|
||||||
cL[1] = bb >> 8 & 0xff;
|
cL[1] = bb >> 8 & 0xff;
|
||||||
cL[2] = bb >> 0 & 0xff;
|
cL[2] = bb >> 0 & 0xff;
|
||||||
cL[3] = 0xff;
|
cL[3] = 0xff;
|
||||||
|
break;
|
||||||
|
|
||||||
cL += BPP;
|
case CRT_PIX_FORMAT_BGR:
|
||||||
|
cL[0] = bb >> 0 & 0xff;
|
||||||
|
cL[1] = bb >> 8 & 0xff;
|
||||||
|
cL[2] = bb >> 16 & 0xff;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CRT_PIX_FORMAT_BGRA:
|
||||||
|
cL[0] = bb >> 0 & 0xff;
|
||||||
|
cL[1] = bb >> 8 & 0xff;
|
||||||
|
cL[2] = bb >> 16 & 0xff;
|
||||||
|
cL[3] = 0xff;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CRT_PIX_FORMAT_ARGB:
|
||||||
|
cL[0] = 0xff;
|
||||||
|
cL[1] = bb >> 16 & 0xff;
|
||||||
|
cL[2] = bb >> 8 & 0xff;
|
||||||
|
cL[3] = bb >> 0 & 0xff;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CRT_PIX_FORMAT_ABGR:
|
||||||
|
cL[0] = 0xff;
|
||||||
|
cL[1] = bb >> 0 & 0xff;
|
||||||
|
cL[2] = bb >> 8 & 0xff;
|
||||||
|
cL[3] = bb >> 16 & 0xff;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cL += bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* duplicate extra lines */
|
/* duplicate extra lines */
|
||||||
|
|||||||
@@ -26,16 +26,57 @@ extern "C" {
|
|||||||
#define CRT_MINOR 3
|
#define CRT_MINOR 3
|
||||||
#define CRT_PATCH 2
|
#define CRT_PATCH 2
|
||||||
|
|
||||||
#include "crt_ntsc.h"
|
|
||||||
|
|
||||||
// frei0r always uses 4 bits per pixel so it is pointless for there to be any other possibilities
|
#define CRT_SYSTEM_NTSC 0 /* standard NTSC */
|
||||||
#define BPP 4
|
#define CRT_SYSTEM_NES 1 /* decode 6 or 9-bit NES pixels */
|
||||||
|
#define CRT_SYSTEM_PV1K 2 /* Casio PV-1000 */
|
||||||
|
#define CRT_SYSTEM_SNES 3 /* SNES - uses RGB */
|
||||||
|
#define CRT_SYSTEM_TEMP 4 /* template implementation */
|
||||||
|
#define CRT_SYSTEM_NTSCVHS 5 /* standard NTSC VHS */
|
||||||
|
#define CRT_SYSTEM_NESRGB 6 /* encode RGB image with NES artifacts */
|
||||||
|
|
||||||
|
/* the system to be compiled */
|
||||||
|
#ifndef CRT_SYSTEM
|
||||||
|
#define CRT_SYSTEM CRT_SYSTEM_NTSC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (CRT_SYSTEM == CRT_SYSTEM_NES)
|
||||||
|
#include "crt_nes.h"
|
||||||
|
#elif (CRT_SYSTEM == CRT_SYSTEM_SNES)
|
||||||
|
#include "crt_snes.h"
|
||||||
|
#elif (CRT_SYSTEM == CRT_SYSTEM_NTSC)
|
||||||
|
#include "crt_ntsc.h"
|
||||||
|
#elif (CRT_SYSTEM == CRT_SYSTEM_PV1K)
|
||||||
|
#include "crt_pv1k.h"
|
||||||
|
#elif (CRT_SYSTEM == CRT_SYSTEM_TEMP)
|
||||||
|
#include "crt_template.h"
|
||||||
|
#elif (CRT_SYSTEM == CRT_SYSTEM_NTSCVHS)
|
||||||
|
#include "crt_ntscvhs.h"
|
||||||
|
#elif (CRT_SYSTEM == CRT_SYSTEM_NESRGB)
|
||||||
|
#include "crt_nesrgb.h"
|
||||||
|
#else
|
||||||
|
#error No system defined
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* NOTE: this library does not use the alpha channel at all */
|
||||||
|
#define CRT_PIX_FORMAT_RGB 0 /* 3 bytes per pixel [R,G,B,R,G,B,R,G,B...] */
|
||||||
|
#define CRT_PIX_FORMAT_BGR 1 /* 3 bytes per pixel [B,G,R,B,G,R,B,G,R...] */
|
||||||
|
#define CRT_PIX_FORMAT_ARGB 2 /* 4 bytes per pixel [A,R,G,B,A,R,G,B...] */
|
||||||
|
#define CRT_PIX_FORMAT_RGBA 3 /* 4 bytes per pixel [R,G,B,A,R,G,B,A...] */
|
||||||
|
#define CRT_PIX_FORMAT_ABGR 4 /* 4 bytes per pixel [A,B,G,R,A,B,G,R...] */
|
||||||
|
#define CRT_PIX_FORMAT_BGRA 5 /* 4 bytes per pixel [B,G,R,A,B,G,R,A...] */
|
||||||
|
|
||||||
|
/* do bloom emulation (side effect: makes screen have black borders) */
|
||||||
|
#define CRT_DO_BLOOM 0 /* does not work for NES */
|
||||||
|
#define CRT_DO_VSYNC 1 /* look for VSYNC */
|
||||||
|
#define CRT_DO_HSYNC 1 /* look for HSYNC */
|
||||||
|
|
||||||
struct CRT {
|
struct CRT {
|
||||||
signed char analog[CRT_INPUT_SIZE];
|
signed char analog[CRT_INPUT_SIZE];
|
||||||
signed char inp[CRT_INPUT_SIZE]; /* CRT input, can be noisy */
|
signed char inp[CRT_INPUT_SIZE]; /* CRT input, can be noisy */
|
||||||
|
|
||||||
int outw, outh; /* output width/height */
|
int outw, outh; /* output width/height */
|
||||||
|
int out_format; /* output pixel format (one of the CRT_PIX_FORMATs) */
|
||||||
unsigned char *out; /* output image */
|
unsigned char *out; /* output image */
|
||||||
|
|
||||||
int hue, brightness, contrast, saturation; /* common monitor settings */
|
int hue, brightness, contrast, saturation; /* common monitor settings */
|
||||||
@@ -44,11 +85,6 @@ struct CRT {
|
|||||||
int blend; /* blend new field onto previous image */
|
int blend; /* blend new field onto previous image */
|
||||||
unsigned v_fac; /* factor to stretch img vertically onto the output img */
|
unsigned v_fac; /* factor to stretch img vertically onto the output img */
|
||||||
|
|
||||||
// these options were previously #defined in crt_core.h
|
|
||||||
int crt_do_vsync;
|
|
||||||
int crt_do_hsync;
|
|
||||||
int do_vhs_noise; /* 0 = no additional vhs noise, 1 = with additional vhs noise */
|
|
||||||
|
|
||||||
/* internal data */
|
/* internal data */
|
||||||
int ccf[CRT_CC_VPER][CRT_CC_SAMPLES]; /* faster color carrier convergence */
|
int ccf[CRT_CC_VPER][CRT_CC_SAMPLES]; /* faster color carrier convergence */
|
||||||
int hsync, vsync; /* keep track of sync over frames */
|
int hsync, vsync; /* keep track of sync over frames */
|
||||||
@@ -61,7 +97,7 @@ struct CRT {
|
|||||||
* f - format of the output image
|
* f - format of the output image
|
||||||
* out - pointer to output image data
|
* out - pointer to output image data
|
||||||
*/
|
*/
|
||||||
extern void crt_init(struct CRT *v, int w, int h, unsigned char *out);
|
extern void crt_init(struct CRT *v, int w, int h, int f, unsigned char *out);
|
||||||
|
|
||||||
/* Updates the output image parameters
|
/* Updates the output image parameters
|
||||||
* w - width of the output image
|
* w - width of the output image
|
||||||
@@ -69,7 +105,7 @@ extern void crt_init(struct CRT *v, int w, int h, unsigned char *out);
|
|||||||
* f - format of the output image
|
* f - format of the output image
|
||||||
* out - pointer to output image data
|
* out - pointer to output image data
|
||||||
*/
|
*/
|
||||||
extern void crt_resize(struct CRT *v, int w, int h, unsigned char *out);
|
extern void crt_resize(struct CRT *v, int w, int h, int f, unsigned char *out);
|
||||||
|
|
||||||
/* Resets the CRT settings back to their defaults */
|
/* Resets the CRT settings back to their defaults */
|
||||||
extern void crt_reset(struct CRT *v);
|
extern void crt_reset(struct CRT *v);
|
||||||
@@ -84,6 +120,14 @@ extern void crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s);
|
|||||||
*/
|
*/
|
||||||
extern void crt_demodulate(struct CRT *v, int noise);
|
extern void crt_demodulate(struct CRT *v, int noise);
|
||||||
|
|
||||||
|
/* Get the bytes per pixel for a certain CRT_PIX_FORMAT_
|
||||||
|
*
|
||||||
|
* format - the format to get the bytes per pixel for
|
||||||
|
*
|
||||||
|
* returns 0 if the specified format does not exist
|
||||||
|
*/
|
||||||
|
extern int crt_bpp4fmt(int format);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/*************************** FIXED POINT SIN/COS *****************************/
|
/*************************** FIXED POINT SIN/COS *****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include "crt_core.h"
|
#include "crt_core.h"
|
||||||
|
|
||||||
#if (CRT_SYSTEM == CRT_SYSTEM_NTSCVHS)
|
#if (CRT_SYSTEM == CRT_SYSTEM_NTSC)
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -137,41 +137,29 @@ crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s)
|
|||||||
int ccburst[CRT_CC_SAMPLES]; /* color phase for burst */
|
int ccburst[CRT_CC_SAMPLES]; /* color phase for burst */
|
||||||
int sn, cs, n, ph;
|
int sn, cs, n, ph;
|
||||||
int inv_phase = 0;
|
int inv_phase = 0;
|
||||||
int aberration = 0;
|
int bpp;
|
||||||
|
|
||||||
if (!s->iirs_initialized) {
|
if (!s->iirs_initialized) {
|
||||||
int y_freq = Y_FREQ_OFF;
|
init_iir(&iirY, L_FREQ, Y_FREQ);
|
||||||
int i_freq = I_FREQ_OFF;
|
init_iir(&iirI, L_FREQ, I_FREQ);
|
||||||
int q_freq = Q_FREQ_OFF;
|
init_iir(&iirQ, L_FREQ, Q_FREQ);
|
||||||
|
|
||||||
switch(s->vhs_mode)
|
|
||||||
{
|
|
||||||
case VHS_OFF:
|
|
||||||
break;
|
|
||||||
case VHS_SP:
|
|
||||||
y_freq = Y_FREQ_SP;
|
|
||||||
i_freq = I_FREQ_SP;
|
|
||||||
q_freq = Q_FREQ_SP;
|
|
||||||
break;
|
|
||||||
case VHS_LP:
|
|
||||||
y_freq = Y_FREQ_LP;
|
|
||||||
i_freq = I_FREQ_LP;
|
|
||||||
q_freq = Q_FREQ_LP;
|
|
||||||
break;
|
|
||||||
case VHS_EP:
|
|
||||||
y_freq = Y_FREQ_EP;
|
|
||||||
i_freq = I_FREQ_EP;
|
|
||||||
q_freq = Q_FREQ_EP;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_iir(&iirY, L_FREQ, y_freq);
|
|
||||||
init_iir(&iirI, L_FREQ, i_freq);
|
|
||||||
init_iir(&iirQ, L_FREQ, q_freq);
|
|
||||||
s->iirs_initialized = 1;
|
s->iirs_initialized = 1;
|
||||||
}
|
}
|
||||||
|
#if CRT_DO_BLOOM
|
||||||
|
if (s->raw) {
|
||||||
|
destw = s->w;
|
||||||
|
desth = s->h;
|
||||||
|
if (destw > ((AV_LEN * 55500) >> 16)) {
|
||||||
|
destw = ((AV_LEN * 55500) >> 16);
|
||||||
|
}
|
||||||
|
if (desth > ((CRT_LINES * 63500) >> 16)) {
|
||||||
|
desth = ((CRT_LINES * 63500) >> 16);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
destw = (AV_LEN * 55500) >> 16;
|
||||||
|
desth = (CRT_LINES * 63500) >> 16;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (s->raw) {
|
if (s->raw) {
|
||||||
destw = s->w;
|
destw = s->w;
|
||||||
desth = s->h;
|
desth = s->h;
|
||||||
@@ -182,7 +170,7 @@ crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s)
|
|||||||
desth = ((CRT_LINES * 64500) >> 16);
|
desth = ((CRT_LINES * 64500) >> 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (s->as_color) {
|
if (s->as_color) {
|
||||||
for (x = 0; x < CRT_CC_SAMPLES; x++) {
|
for (x = 0; x < CRT_CC_SAMPLES; x++) {
|
||||||
n = s->hue + x * (360 / CRT_CC_SAMPLES);
|
n = s->hue + x * (360 / CRT_CC_SAMPLES);
|
||||||
@@ -199,6 +187,10 @@ crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s)
|
|||||||
memset(ccmodQ, 0, sizeof(ccmodQ));
|
memset(ccmodQ, 0, sizeof(ccmodQ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bpp = crt_bpp4fmt(s->format);
|
||||||
|
if (bpp == 0) {
|
||||||
|
return; /* just to be safe */
|
||||||
|
}
|
||||||
xo = AV_BEG + s->xoffset + (AV_LEN - destw) / 2;
|
xo = AV_BEG + s->xoffset + (AV_LEN - destw) / 2;
|
||||||
yo = CRT_TOP + s->yoffset + (CRT_LINES - desth) / 2;
|
yo = CRT_TOP + s->yoffset + (CRT_LINES - desth) / 2;
|
||||||
|
|
||||||
@@ -209,9 +201,7 @@ crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s)
|
|||||||
|
|
||||||
/* align signal */
|
/* align signal */
|
||||||
xo = (xo & ~3);
|
xo = (xo & ~3);
|
||||||
if (s->do_aberration) {
|
|
||||||
aberration = ((rand() % 12) - 8) + 14;
|
|
||||||
}
|
|
||||||
for (n = 0; n < CRT_VRES; n++) {
|
for (n = 0; n < CRT_VRES; n++) {
|
||||||
int t; /* time */
|
int t; /* time */
|
||||||
signed char *line = &v->analog[n * CRT_HRES];
|
signed char *line = &v->analog[n * CRT_HRES];
|
||||||
@@ -238,13 +228,11 @@ crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s)
|
|||||||
while (t < (offs[3] * CRT_HRES / 100)) line[t++] = BLANK_LEVEL;
|
while (t < (offs[3] * CRT_HRES / 100)) line[t++] = BLANK_LEVEL;
|
||||||
} else {
|
} else {
|
||||||
int cb;
|
int cb;
|
||||||
if (n < (CRT_VRES - aberration)) {
|
|
||||||
/* video line */
|
/* video line */
|
||||||
while (t < SYNC_BEG) line[t++] = BLANK_LEVEL; /* FP */
|
while (t < SYNC_BEG) line[t++] = BLANK_LEVEL; /* FP */
|
||||||
while (t < BW_BEG) line[t++] = SYNC_LEVEL; /* SYNC */
|
while (t < BW_BEG) line[t++] = SYNC_LEVEL; /* SYNC */
|
||||||
}
|
|
||||||
while (t < AV_BEG) line[t++] = BLANK_LEVEL; /* BW + CB + BP */
|
while (t < AV_BEG) line[t++] = BLANK_LEVEL; /* BW + CB + BP */
|
||||||
|
|
||||||
if (n < CRT_TOP) {
|
if (n < CRT_TOP) {
|
||||||
while (t < CRT_HRES) line[t++] = BLANK_LEVEL;
|
while (t < CRT_HRES) line[t++] = BLANK_LEVEL;
|
||||||
}
|
}
|
||||||
@@ -263,12 +251,6 @@ crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s->vhs_mode != VHS_OFF)
|
|
||||||
{
|
|
||||||
/* reset hsync every frame so only the bottom part is warped */
|
|
||||||
v->hsync = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (y = 0; y < desth; y++) {
|
for (y = 0; y < desth; y++) {
|
||||||
int field_offset;
|
int field_offset;
|
||||||
int sy;
|
int sy;
|
||||||
@@ -293,11 +275,34 @@ crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s)
|
|||||||
int ire; /* composite signal */
|
int ire; /* composite signal */
|
||||||
int xoff;
|
int xoff;
|
||||||
|
|
||||||
pix = s->data + ((((x * s->w) / destw) + sy) * BPP);
|
pix = s->data + ((((x * s->w) / destw) + sy) * bpp);
|
||||||
|
switch (s->format) {
|
||||||
|
case CRT_PIX_FORMAT_RGB:
|
||||||
|
case CRT_PIX_FORMAT_RGBA:
|
||||||
rA = pix[0];
|
rA = pix[0];
|
||||||
gA = pix[1];
|
gA = pix[1];
|
||||||
bA = pix[2];
|
bA = pix[2];
|
||||||
|
break;
|
||||||
|
case CRT_PIX_FORMAT_BGR:
|
||||||
|
case CRT_PIX_FORMAT_BGRA:
|
||||||
|
rA = pix[2];
|
||||||
|
gA = pix[1];
|
||||||
|
bA = pix[0];
|
||||||
|
break;
|
||||||
|
case CRT_PIX_FORMAT_ARGB:
|
||||||
|
rA = pix[1];
|
||||||
|
gA = pix[2];
|
||||||
|
bA = pix[3];
|
||||||
|
break;
|
||||||
|
case CRT_PIX_FORMAT_ABGR:
|
||||||
|
rA = pix[3];
|
||||||
|
gA = pix[2];
|
||||||
|
bA = pix[1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rA = gA = bA = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* RGB to YIQ */
|
/* RGB to YIQ */
|
||||||
fy = (19595 * rA + 38470 * gA + 7471 * bA) >> 14;
|
fy = (19595 * rA + 38470 * gA + 7471 * bA) >> 14;
|
||||||
@@ -319,15 +324,8 @@ crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s)
|
|||||||
}
|
}
|
||||||
for (n = 0; n < CRT_CC_VPER; n++) {
|
for (n = 0; n < CRT_CC_VPER; n++) {
|
||||||
for (x = 0; x < CRT_CC_SAMPLES; x++) {
|
for (x = 0; x < CRT_CC_SAMPLES; x++) {
|
||||||
if(s->vhs_mode != VHS_OFF)
|
|
||||||
{
|
|
||||||
v->ccf[n][x] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v->ccf[n][x] = iccf[x] << 7;
|
v->ccf[n][x] = iccf[x] << 7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,17 +8,16 @@
|
|||||||
* Discord: https://discord.com/invite/hdYctSmyQJ
|
* Discord: https://discord.com/invite/hdYctSmyQJ
|
||||||
*/
|
*/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
#ifndef _CRT_NTSC_VHS_H_
|
#ifndef _CRT_NTSC_H_
|
||||||
#define _CRT_NTSC_VHS_H_
|
#define _CRT_NTSC_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* crt_ntscvhs.h
|
/* crt_ntsc.h
|
||||||
*
|
*
|
||||||
* An interface to convert a digital image to an analog NTSC signal with VHS
|
* An interface to convert a digital image to an analog NTSC signal.
|
||||||
* quality and some optional signal aberration at the bottom.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
/* 0 = vertical chroma (228 chroma clocks per line) */
|
/* 0 = vertical chroma (228 chroma clocks per line) */
|
||||||
@@ -96,32 +95,11 @@ extern "C" {
|
|||||||
/* somewhere between 7 and 12 cycles */
|
/* somewhere between 7 and 12 cycles */
|
||||||
#define CB_CYCLES 10
|
#define CB_CYCLES 10
|
||||||
|
|
||||||
#define VHS_OFF 0
|
|
||||||
#define VHS_SP 1
|
|
||||||
#define VHS_LP 2
|
|
||||||
#define VHS_EP 3
|
|
||||||
|
|
||||||
#define VHS_MODE VHS_OFF
|
|
||||||
|
|
||||||
/* frequencies for bandlimiting */
|
/* frequencies for bandlimiting */
|
||||||
#define L_FREQ 1431818 /* full line */
|
#define L_FREQ 1431818 /* full line */
|
||||||
|
#define Y_FREQ 420000 /* Luma (Y) 4.2 MHz of the 14.31818 MHz */
|
||||||
#define Y_FREQ_OFF 420000 /* Luma (Y) 4.2 MHz of the 14.31818 MHz */
|
#define I_FREQ 150000 /* Chroma (I) 1.5 MHz of the 14.31818 MHz */
|
||||||
#define I_FREQ_OFF 150000 /* Chroma (I) 1.5 MHz of the 14.31818 MHz */
|
#define Q_FREQ 55000 /* Chroma (Q) 0.55 MHz of the 14.31818 MHz */
|
||||||
#define Q_FREQ_OFF 55000 /* Chroma (Q) 0.55 MHz of the 14.31818 MHz */
|
|
||||||
|
|
||||||
#define Y_FREQ_SP 300000 /* Luma (Y) 3.0 MHz of the 14.31818 MHz */
|
|
||||||
#define I_FREQ_SP 62700 /* Chroma (I) 627 kHz of the 14.31818 MHz */
|
|
||||||
#define Q_FREQ_SP 62700 /* Chroma (Q) 627 kHz of the 14.31818 MHz */
|
|
||||||
|
|
||||||
#define Y_FREQ_LP 240000 /* Luma (Y) 2.4 MHz of the 14.31818 MHz */
|
|
||||||
#define I_FREQ_LP 40000 /* Chroma (I) 400 kHz of the 14.31818 MHz */
|
|
||||||
#define Q_FREQ_LP 40000 /* Chroma (Q) 400 kHz of the 14.31818 MHz */
|
|
||||||
|
|
||||||
#define Y_FREQ_EP 200000 /* Luma (Y) 2.0 MHz of the 14.31818 MHz */
|
|
||||||
#define I_FREQ_EP 37000 /* Chroma (I) 370 kHz of the 14.31818 MHz */
|
|
||||||
#define Q_FREQ_EP 37000 /* Chroma (Q) 370 kHz of the 14.31818 MHz */
|
|
||||||
|
|
||||||
|
|
||||||
/* IRE units (100 = 1.0V, -40 = 0.0V) */
|
/* IRE units (100 = 1.0V, -40 = 0.0V) */
|
||||||
#define WHITE_LEVEL 100
|
#define WHITE_LEVEL 100
|
||||||
@@ -132,6 +110,7 @@ extern "C" {
|
|||||||
|
|
||||||
struct NTSC_SETTINGS {
|
struct NTSC_SETTINGS {
|
||||||
const unsigned char *data; /* image data */
|
const unsigned char *data; /* image data */
|
||||||
|
int format; /* pix format (one of the CRT_PIX_FORMATs in crt_core.h) */
|
||||||
int w, h; /* width and height of image */
|
int w, h; /* width and height of image */
|
||||||
int raw; /* 0 = scale image to fit monitor, 1 = don't scale */
|
int raw; /* 0 = scale image to fit monitor, 1 = don't scale */
|
||||||
int as_color; /* 0 = monochrome, 1 = full color */
|
int as_color; /* 0 = monochrome, 1 = full color */
|
||||||
@@ -140,14 +119,6 @@ struct NTSC_SETTINGS {
|
|||||||
int hue; /* 0-359 */
|
int hue; /* 0-359 */
|
||||||
int xoffset; /* x offset in sample space. 0 is minimum value */
|
int xoffset; /* x offset in sample space. 0 is minimum value */
|
||||||
int yoffset; /* y offset in # of lines. 0 is minimum value */
|
int yoffset; /* y offset in # of lines. 0 is minimum value */
|
||||||
int do_aberration; /* 0 = no aberration, 1 = with aberration */
|
|
||||||
|
|
||||||
// these are changed by the vhs mode
|
|
||||||
int vhs_mode;
|
|
||||||
int y_freq;
|
|
||||||
int i_freq;
|
|
||||||
int q_freq;
|
|
||||||
|
|
||||||
/* make sure your NTSC_SETTINGS struct is zeroed out before you do anything */
|
/* make sure your NTSC_SETTINGS struct is zeroed out before you do anything */
|
||||||
int iirs_initialized; /* internal state */
|
int iirs_initialized; /* internal state */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "frei0r.h"
|
#include "frei0r.h"
|
||||||
#include "frei0r/math.h"
|
#include "frei0r/math.h"
|
||||||
|
|
||||||
#include "crt_core.h"
|
#include "crt_core.h"
|
||||||
|
|
||||||
// the actual NTSC emulation code is modified from here: https://github.com/LMP88959/NTSC-CRT
|
// the actual NTSC emulation code is from here: https://github.com/LMP88959/NTSC-CRT
|
||||||
|
|
||||||
|
|
||||||
typedef struct ntsc_instance
|
typedef struct ntsc_instance
|
||||||
{
|
{
|
||||||
@@ -15,16 +17,15 @@ typedef struct ntsc_instance
|
|||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
struct CRT crt;
|
struct CRT crt;
|
||||||
struct NTSC_SETTINGS ntsc_settings;
|
struct NTSC_SETTINGS ntsc;
|
||||||
|
|
||||||
int noise;
|
int noise;
|
||||||
double vhs_speed;
|
|
||||||
|
|
||||||
int field;
|
int field;
|
||||||
int progressive;
|
int progressive;
|
||||||
|
|
||||||
} ntsc_instance_t;
|
} ntsc_instance_t;
|
||||||
|
|
||||||
|
|
||||||
// these functions are for frei0r
|
// these functions are for frei0r
|
||||||
// mostly copy/paste/slightly modified from the other frei0r effects
|
// mostly copy/paste/slightly modified from the other frei0r effects
|
||||||
int f0r_init()
|
int f0r_init()
|
||||||
@@ -44,8 +45,8 @@ void f0r_get_plugin_info(f0r_plugin_info_t* info)
|
|||||||
info->color_model = F0R_COLOR_MODEL_RGBA8888;
|
info->color_model = F0R_COLOR_MODEL_RGBA8888;
|
||||||
info->frei0r_version = FREI0R_MAJOR_VERSION;
|
info->frei0r_version = FREI0R_MAJOR_VERSION;
|
||||||
info->major_version = 0;
|
info->major_version = 0;
|
||||||
info->minor_version = 1;
|
info->minor_version = 2;
|
||||||
info->num_params = 8;
|
info->num_params = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void f0r_get_param_info(f0r_param_info_t* info, int param_index)
|
void f0r_get_param_info(f0r_param_info_t* info, int param_index)
|
||||||
@@ -59,49 +60,20 @@ void f0r_get_param_info(f0r_param_info_t* info, int param_index)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
info->name = "VHS Speed";
|
|
||||||
info->explanation = "Simulates VHS. 0 = off, 1 = SP, 2 = LP, 3 = EP";
|
|
||||||
info->type = F0R_PARAM_DOUBLE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
info->name = "VHS Noise";
|
|
||||||
info->explanation = "Toggles VHS noise at the bottom of the screen";
|
|
||||||
info->type = F0R_PARAM_BOOL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
info->name = "Aberration";
|
|
||||||
info->explanation = "Toggles VHS aberration at the bottom of the screen. Not visible if V-sync is on.";
|
|
||||||
info->type = F0R_PARAM_BOOL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
info->name = "Force V-sync";
|
|
||||||
info->explanation = "Forces V-sync even when the signal is really noisy.";
|
|
||||||
info->type = F0R_PARAM_BOOL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
info->name = "Force H-sync";
|
|
||||||
info->explanation = "Forces V-sync even when the signal is really noisy.";
|
|
||||||
info->type = F0R_PARAM_BOOL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
info->name = "Progressive Scan";
|
info->name = "Progressive Scan";
|
||||||
info->explanation = "Toggles progressive scan (Interlaced if off).";
|
info->explanation = "Toggles progressive scan (Interlaced if off).";
|
||||||
info->type = F0R_PARAM_BOOL;
|
info->type = F0R_PARAM_BOOL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case 2:
|
||||||
info->name = "Blend";
|
info->name = "Scanlines";
|
||||||
info->explanation = "Blends frames.";
|
info->explanation = "Draw borders between scanlines.";
|
||||||
info->type = F0R_PARAM_BOOL;
|
info->type = F0R_PARAM_BOOL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
|
f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
|
||||||
{
|
{
|
||||||
ntsc_instance_t* inst = (ntsc_instance_t*)calloc(1, sizeof(*inst));
|
ntsc_instance_t* inst = (ntsc_instance_t*)calloc(1, sizeof(*inst));
|
||||||
@@ -109,35 +81,27 @@ f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
|
|||||||
inst->width = width;
|
inst->width = width;
|
||||||
inst->height = height;
|
inst->height = height;
|
||||||
|
|
||||||
inst->vhs_speed = 0.0;
|
inst->ntsc.format = CRT_PIX_FORMAT_RGBA;
|
||||||
inst->field = 0;
|
inst->ntsc.w = width;
|
||||||
inst->progressive = 1;
|
inst->ntsc.h = height;
|
||||||
|
inst->ntsc.raw = 0;
|
||||||
crt_init(&(inst->crt), width, height, NULL);
|
inst->ntsc.field = 0;
|
||||||
|
inst->ntsc.frame = 0;
|
||||||
// init NTSC_SETTINGS
|
inst->ntsc.as_color = 1;
|
||||||
inst->ntsc_settings.data = NULL;
|
inst->ntsc.hue = 0;
|
||||||
inst->ntsc_settings.w = width;
|
inst->ntsc.xoffset = 0;
|
||||||
inst->ntsc_settings.h = height;
|
inst->ntsc.yoffset = 0;
|
||||||
inst->ntsc_settings.raw = 0;
|
inst->ntsc.iirs_initialized = 0;
|
||||||
inst->ntsc_settings.as_color = 1;
|
|
||||||
inst->ntsc_settings.field = 0;
|
|
||||||
inst->ntsc_settings.frame = 0;
|
|
||||||
inst->ntsc_settings.hue = 0;
|
|
||||||
inst->ntsc_settings.xoffset = 0;
|
|
||||||
inst->ntsc_settings.yoffset = 0;
|
|
||||||
inst->ntsc_settings.do_aberration = 0;
|
|
||||||
|
|
||||||
// these are changed by the vhs mode
|
|
||||||
inst->ntsc_settings.vhs_mode = 0;
|
|
||||||
inst->ntsc_settings.y_freq = 0;
|
|
||||||
inst->ntsc_settings.i_freq = 0;
|
|
||||||
inst->ntsc_settings.q_freq = 0;
|
|
||||||
|
|
||||||
/* make sure your NTSC_SETTINGS struct is zeroed out before you do anything */
|
|
||||||
inst->ntsc_settings.iirs_initialized = 0;
|
|
||||||
|
|
||||||
inst->noise = 0;
|
inst->noise = 0;
|
||||||
|
inst->progressive = 0;
|
||||||
|
inst->field = 0;
|
||||||
|
|
||||||
|
crt_init(&(inst->crt), width, height, CRT_PIX_FORMAT_RGBA, NULL);
|
||||||
|
inst->crt.blend = 0;
|
||||||
|
inst->crt.scanlines = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (f0r_instance_t)inst;
|
return (f0r_instance_t)inst;
|
||||||
}
|
}
|
||||||
@@ -155,29 +119,13 @@ void f0r_set_param_value(f0r_instance_t instance, f0r_param_t param, int param_i
|
|||||||
switch(param_index)
|
switch(param_index)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
inst->noise = *((double*)param) * 100;
|
inst->noise = *((double*)param) * 200;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
inst->ntsc_settings.vhs_mode = (int)CLAMP(*((double*)param) * 4, 0, 4);
|
|
||||||
inst->ntsc_settings.iirs_initialized = 0;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
inst->crt.do_vhs_noise = (*((double*)param) >= 0.5);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
inst->ntsc_settings.do_aberration = (*((double*)param) >= 0.5);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
inst->crt.crt_do_vsync = !(*((double*)param) >= 0.5);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
inst->crt.crt_do_hsync = !(*((double*)param) >= 0.5);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
inst->progressive = (*((double*)param) >= 0.5);
|
inst->progressive = (*((double*)param) >= 0.5);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 2:
|
||||||
inst->crt.blend = (*((double*)param) >= 0.5);
|
inst->crt.scanlines = (*((double*)param) >= 0.5);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,28 +136,13 @@ void f0r_get_param_value(f0r_instance_t instance, f0r_param_t param, int param_i
|
|||||||
switch(param_index)
|
switch(param_index)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
*((double*)param) = (inst->noise / 100);
|
*((double*)param) = (inst->noise / 200);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
*((double*)param) = (inst->ntsc_settings.vhs_mode / 4);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*((double*)param) = (inst->crt.do_vhs_noise ? 1.0 : 0.0);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
*((double*)param) = (inst->ntsc_settings.do_aberration ? 1.0 : 0.0);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
*((double*)param) = !(inst->crt.crt_do_vsync ? 1.0 : 0.0);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
*((double*)param) = !(inst->crt.crt_do_hsync ? 1.0 : 0.0);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
*((double*)param) = (inst->progressive ? 1.0 : 0.0);
|
*((double*)param) = (inst->progressive ? 1.0 : 0.0);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 2:
|
||||||
*((double*)param) = (inst->crt.blend ? 1.0 : 0.0);
|
*((double*)param) = (inst->crt.scanlines ? 1.0 : 0.0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,19 +152,36 @@ void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, u
|
|||||||
{
|
{
|
||||||
ntsc_instance_t* inst = (ntsc_instance_t*)instance;
|
ntsc_instance_t* inst = (ntsc_instance_t*)instance;
|
||||||
|
|
||||||
inst->crt.out = (char*)outframe;
|
// clear the output frame
|
||||||
inst->ntsc_settings.data = (const char*)inframe;
|
memset(outframe, 0, inst->width * inst->height * sizeof(uint32_t));
|
||||||
|
inst->crt.blend = 0;
|
||||||
|
|
||||||
inst->ntsc_settings.field = inst->field & 1;
|
// set everything up for the simulation
|
||||||
if (inst->ntsc_settings.field == 0) {
|
inst->crt.out = (char*)outframe;
|
||||||
|
inst->ntsc.data = (const char*)inframe;
|
||||||
|
|
||||||
|
_render_field:
|
||||||
|
inst->ntsc.field = inst->field & 1;
|
||||||
|
|
||||||
|
if (inst->ntsc.field == 0) {
|
||||||
/* a frame is two fields */
|
/* a frame is two fields */
|
||||||
inst->ntsc_settings.frame ^= 1;
|
inst->ntsc.frame ^= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
crt_modulate(&(inst->crt), &(inst->ntsc_settings));
|
// encode and decode ntsc signal
|
||||||
|
crt_modulate(&(inst->crt), &(inst->ntsc));
|
||||||
crt_demodulate(&(inst->crt), inst->noise);
|
crt_demodulate(&(inst->crt), inst->noise);
|
||||||
if(!inst->progressive)
|
|
||||||
{
|
|
||||||
inst->field ^= 1;
|
inst->field ^= 1;
|
||||||
|
// if we are in progressive mode, we render both fields onto the frame.
|
||||||
|
// in interlaced mode, we will hit the opposite field on the next frame.
|
||||||
|
if(inst->field && inst->progressive)
|
||||||
|
{
|
||||||
|
// if we are not leaving scanlines blank, we will want to blend the frames in progressive mode
|
||||||
|
if(!inst->crt.scanlines)
|
||||||
|
{
|
||||||
|
inst->crt.blend = 1;
|
||||||
|
}
|
||||||
|
goto _render_field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user