-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathcrt_ntscvhs.h
153 lines (134 loc) · 5.77 KB
/
crt_ntscvhs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*****************************************************************************/
/*
* NTSC/CRT - integer-only NTSC video signal encoding / decoding emulation
*
* by EMMIR 2018-2023
*
* YouTube: https://www.youtube.com/@EMMIR_KC/videos
* Discord: https://discord.com/invite/hdYctSmyQJ
*/
/*****************************************************************************/
#ifndef _CRT_NTSC_VHS_H_
#define _CRT_NTSC_VHS_H_
#ifdef __cplusplus
extern "C" {
#endif
/* crt_ntscvhs.h
*
* An interface to convert a digital image to an analog NTSC signal with VHS
* quality and some optional signal aberration at the bottom.
*
*/
/* 0 = vertical chroma (228 chroma clocks per line) */
/* 1 = checkered chroma (227.5 chroma clocks per line) */
#define CRT_CHROMA_PATTERN 1
/* set to zero to remove the noise at the bottom of the frame */
#define CRT_VHS_NOISE 1
/* chroma clocks (subcarrier cycles) per line */
#if (CRT_CHROMA_PATTERN == 1)
#define CRT_CC_LINE 2275
#else
/* this will give the 'rainbow' effect in the famous waterfall scene */
#define CRT_CC_LINE 2280
#endif
/* NOTE, in general, increasing CRT_CB_FREQ reduces blur and bleed */
#define CRT_CB_FREQ 4 /* carrier frequency relative to sample rate */
#define CRT_HRES (CRT_CC_LINE * CRT_CB_FREQ / 10) /* horizontal res */
#define CRT_VRES 262 /* vertical resolution */
#define CRT_INPUT_SIZE (CRT_HRES * CRT_VRES)
#define CRT_TOP 21 /* first line with active video */
#define CRT_BOT 261 /* final line with active video */
#define CRT_LINES (CRT_BOT - CRT_TOP) /* number of active video lines */
#define CRT_CC_SAMPLES 4 /* samples per chroma period (samples per 360 deg) */
#define CRT_CC_VPER 1 /* vertical period in which the artifacts repeat */
/* search windows, in samples */
#define CRT_HSYNC_WINDOW 8
#define CRT_VSYNC_WINDOW 8
/* accumulated signal threshold required for sync detection.
* Larger = more stable, until it's so large that it is never reached in which
* case the CRT won't be able to sync
*/
#define CRT_HSYNC_THRESH 4
#define CRT_VSYNC_THRESH 94
/*
* FULL HORIZONTAL LINE SIGNAL (~63500 ns)
* |---------------------------------------------------------------------------|
* HBLANK (~10900 ns) ACTIVE VIDEO (~52600 ns)
* |-------------------||------------------------------------------------------|
*
*
* WITHIN HBLANK PERIOD:
*
* FP (~1500 ns) SYNC (~4700 ns) BW (~600 ns) CB (~2500 ns) BP (~1600 ns)
* |--------------||---------------||------------||-------------||-------------|
* BLANK SYNC BLANK BLANK BLANK
*
*/
#define LINE_BEG 0
#define FP_ns 1500 /* front porch */
#define SYNC_ns 4700 /* sync tip */
#define BW_ns 600 /* breezeway */
#define CB_ns 2500 /* color burst */
#define BP_ns 1600 /* back porch */
#define AV_ns 52600 /* active video */
#define HB_ns (FP_ns + SYNC_ns + BW_ns + CB_ns + BP_ns) /* h blank */
/* line duration should be ~63500 ns */
#define LINE_ns (FP_ns + SYNC_ns + BW_ns + CB_ns + BP_ns + AV_ns)
/* convert nanosecond offset to its corresponding point on the sampled line */
#define ns2pos(ns) ((ns) * CRT_HRES / LINE_ns)
/* starting points for all the different pulses */
#define FP_BEG ns2pos(0)
#define SYNC_BEG ns2pos(FP_ns)
#define BW_BEG ns2pos(FP_ns + SYNC_ns)
#define CB_BEG ns2pos(FP_ns + SYNC_ns + BW_ns)
#define BP_BEG ns2pos(FP_ns + SYNC_ns + BW_ns + CB_ns)
#define AV_BEG ns2pos(HB_ns)
#define AV_LEN ns2pos(AV_ns)
/* somewhere between 7 and 12 cycles */
#define CB_CYCLES 10
#define VHS_SP 0
#define VHS_LP 1
#define VHS_EP 2
#define VHS_MODE VHS_SP
/* frequencies for bandlimiting */
#if (VHS_MODE == VHS_SP)
#define L_FREQ 1431818 /* full line */
#define Y_FREQ 300000 /* Luma (Y) 3.0 MHz of the 14.31818 MHz */
#define I_FREQ 62700 /* Chroma (I) 627 kHz of the 14.31818 MHz */
#define Q_FREQ 62700 /* Chroma (Q) 627 kHz of the 14.31818 MHz */
#elif (VHS_MODE == VHS_LP)
#define L_FREQ 1431818 /* full line */
#define Y_FREQ 240000 /* Luma (Y) 2.4 MHz of the 14.31818 MHz */
#define I_FREQ 40000 /* Chroma (I) 400 kHz of the 14.31818 MHz */
#define Q_FREQ 40000 /* Chroma (Q) 400 kHz of the 14.31818 MHz */
#elif (VHS_MODE == VHS_EP)
#define L_FREQ 1431818 /* full line */
#define Y_FREQ 200000 /* Luma (Y) 2.0 MHz of the 14.31818 MHz */
#define I_FREQ 37000 /* Chroma (I) 370 kHz of the 14.31818 MHz */
#define Q_FREQ 37000 /* Chroma (Q) 370 kHz of the 14.31818 MHz */
#endif
/* IRE units (100 = 1.0V, -40 = 0.0V) */
#define WHITE_LEVEL 100
#define BURST_LEVEL 20
#define BLACK_LEVEL 7
#define BLANK_LEVEL 0
#define SYNC_LEVEL -40
struct NTSC_SETTINGS {
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 raw; /* 0 = scale image to fit monitor, 1 = don't scale */
int as_color; /* 0 = monochrome, 1 = full color */
int field; /* 0 = even, 1 = odd */
int frame; /* 0 = even, 1 = odd */
int hue; /* 0-359 */
int xoffset; /* x offset in sample space. 0 is minimum value */
int yoffset; /* y offset in # of lines. 0 is minimum value */
int do_aberration; /* 0 = no aberration, 1 = with aberration */
/* make sure your NTSC_SETTINGS struct is zeroed out before you do anything */
int iirs_initialized; /* internal state */
};
#ifdef __cplusplus
}
#endif
#endif