aboutsummaryrefslogtreecommitdiffstats
path: root/src/tv/convergence.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tv/convergence.c')
-rw-r--r--src/tv/convergence.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/tv/convergence.c b/src/tv/convergence.c
new file mode 100644
index 0000000..ee74d24
--- /dev/null
+++ b/src/tv/convergence.c
@@ -0,0 +1,109 @@
+/* Color Convergence test image generator
+ *
+ * (C) 2019 by Andreas Eversberg <jolly@eversberg.eu>
+ * All Rights Reserved
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "../libsample/sample.h"
+#include "convergence.h"
+
+#define GRID_LINES (4 * thick)
+#define GRID_HEIGHT 40
+#define GRID_HEIGHT2 20
+#define CENTER_LINE (287 - 2)
+
+#define GRID_WIDTH 0.0000027
+#define GRID_WIDTH2 0.00000135
+#define RAMP_WIDTH (0.0000002 * thick)
+
+#define GRID_LEVEL 1.0
+#define FIELD_LEVEL 0.00
+
+/* create cosine ramp, so that the bandwidth is not higher than 2 * width of the ramp(0..1) */
+static inline double ramp(double x)
+{
+ return 0.5 - 0.5 * cos(x * M_PI);
+}
+
+int convergence_gen_line(sample_t *sample, double x, double samplerate, double line_start, double line_end, int line, double thick)
+{
+ double step = 1.0 / samplerate;
+ int i = 0;
+ double render_start, render_end, center_x;
+
+ /* skip x to line_start */
+ while (x < line_start && x < line_end) {
+ i++;
+ x += step;
+ }
+ if (x >= line_end)
+ return i;
+
+ /* calculate phase for ramp start of center line */
+ center_x = (line_end - line_start) / 2.0 + line_start;
+
+ /* calculate position in grid:
+ * get the distance below the center line (line - CENTER_LINE)
+ * then be sure not to get negative value: add a multiple of the grid period
+ * then use modulo to get the distance below the grid line */
+ if (((line - CENTER_LINE + GRID_HEIGHT*40) % GRID_HEIGHT) < GRID_LINES) {
+ /* grid line after middle field */
+ while (x < line_end) {
+ sample[i++] = GRID_LEVEL;
+ x += step;
+ }
+ } else {
+ while (1) {
+ /* calculate position for next ramp:
+ * get the distance to center (center_x - x - RAMP_WIDTH)
+ * then be sure not to get negative value: add a multiple of the grid period
+ * then use fmod to get the next ramp start */
+ if (((line - CENTER_LINE + GRID_HEIGHT2*40) % GRID_HEIGHT2) < GRID_LINES)
+ render_start = fmod(center_x - x - RAMP_WIDTH + GRID_WIDTH2*40.0, GRID_WIDTH2) + x;
+ else
+ render_start = fmod(center_x - x - RAMP_WIDTH + GRID_WIDTH*40.0, GRID_WIDTH) + x;
+ /* draw background field up to grid start */
+ while (x < render_start && x < line_end) {
+ sample[i++] = FIELD_LEVEL;
+ x += step;
+ }
+ if (x >= line_end)
+ break;
+ /* ramp up to grid level */
+ render_end = render_start + RAMP_WIDTH;
+ while (x < render_end && x < line_end) {
+ sample[i++] = ramp((x - render_start) / RAMP_WIDTH) * (GRID_LEVEL - FIELD_LEVEL) + FIELD_LEVEL;
+ x += step;
+ }
+ if (x >= line_end)
+ break;
+ render_start = render_end;
+ /* ramp down to field level */
+ render_end = render_start + RAMP_WIDTH;
+ while (x < render_end && x < line_end) {
+ sample[i++] = ramp((x - render_start) / RAMP_WIDTH) * (FIELD_LEVEL - GRID_LEVEL) + GRID_LEVEL;
+ x += step;
+ }
+ if (x >= line_end)
+ break;
+ }
+ }
+
+ return i;
+}