Plan 9 from Bell Labs’s /usr/web/sources/contrib/maht/inferno/appl/cmd/ntsc_pal/ntsc_pal.b

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


implement NTSC_PAL;

include "ntsc_pal.m";

include "draw.m";
draw : Draw;
include "math.m";
math : Math;

include "sys.m";
sys: Sys;

include "../ppm_dv/ppm_dv.m";
ppmdv : PPM_dv;
Sequence, Pixel, Samples : import ppmdv;


include "../fft/short_fft.m";
fft : FFT;
Complexes : import fft;
C_from_file : import fft;

fft_dir : con "/usr/m/water_fft";
sample_size : con 128;
sample_power : int;

higher_power(x: int) : int
{
	pwr := 1;
	m := 0;
	while(pwr < x) {
		m++;
		pwr = pwr << 1;
		if(m > 100) return -1;
	}
	return m;
}

fft_pixel(fd : ref Sys->FD, s : ref Sequence, start_frame : big, x, y, rgb : int) : ref Sys->FD
{
	cs := fft->C_from_ints(s.frame_pixel(start_frame, sample_size, x, y, rgb), real s.maxvalue);
	cs.fft(1, sample_power);
	return cs.save(fd, fft_dir, start_frame, x, y);
}

generate_ffts(directory : string, start_frame, end_frame : big) : ref Sequence
{
	s := ppmdv->new_sequence(directory);
#	for(x := 0; x < s.width; x++) {
#		for( y:= 0; y < s.height; y++) {
	for(x := 103; x < 150; x++) {
		for( y:= 116; y < 150; y++) {
			for(frame := start_frame; frame < end_frame; frame++) {
sys->print("x %d y%d frame %bd\n", x, y, frame);
				fd := fft_pixel(nil, s, frame, x, y, 'R');
				fft_pixel(fd, s, frame, x, y, 'G');
				fft_pixel(fd, s, frame, x, y, 'B');
			}
		}
	}
	return s;
}

interpolate_ffts(frame : big, x,y, rgb : int, r : real) : ref Complexes
{
	case rgb {
		'R' => rgb = Rp;
		'G' => rgb = Gp;
		'B' => rgb = Bp;
	}
	lowc := C_from_file(sys->sprint("%s/%bd.%d-%d.fft", fft_dir, frame, x, y), 3, rgb);
	highc := C_from_file(sys->sprint("%s/%bd.%d-%d.fft", fft_dir, frame + big 1, x, y), 3, rgb);
	lowc.interpolate(highc, r);
	return lowc;
}

resample(srcdir : string, src_start, src_end : big, targdir : string, trg_start, trg_end : big)
{
	s := generate_ffts(srcdir, src_start, src_end);
	sys->print("%s", s.info());

	nums := big 1 + src_end - src_start;
	numt := big 1 + trg_end - trg_start;

	st := 1.0 / real nums;
	tt := 1.0 / real numt;

	r := tt / st;
	sys->print("r %f\n", r); # 25 / 30 src_speed / trg_speed
	for(tf := big 0; tf < numt; tf++) {
		sf := real tf * r;
		s1 := int math->floor(sf);
		r2 := sf - real s1;
		r1 := 1.0 - r2;
		for(x:=0; x < s.width; x++) {
			for( y := 0; y < s.height; y++) {
				cr := interpolate_ffts(src_start + big s1, x, y, 'R', r1);
				cg := interpolate_ffts(src_start + big s1, x, y, 'G', r1);
				cb := interpolate_ffts(src_start + big s1, x, y, 'B', r1);
			}
		}
break;
	}
}

test1() {
	start_frame := big 100;
	s := ppmdv->new_sequence("/usr/m/water_pal");
	s.width = 1; s.height = 1; sys->print("one pixel only 0,0\n");
	ints := s.frame_pixel(start_frame, sample_size, 0, 0, 'R');
	cs := fft->C_from_ints(ints, real s.maxvalue);
	cs.print("x", "y");
	fd := cs.save(nil, fft_dir, start_frame, 0, 0);  # r only !
	if(fd == nil) {
		sys->print("NOT SAVED\n");
	} else {
		sys->print("SAVED / NOW LOAD\n");
		cl := C_from_file("/usr/m/water_fft/100.0-0.fft", 1, 0);
		cl.print("x'", "y'");
	}
}


test2() {
	start_frame := big 100;
	s := ppmdv->new_sequence("/usr/m/water_pal");
	s.width = 1; s.height = 1; sys->print("one pixel only 0,0\n");
	ints := s.frame_pixel(start_frame, sample_size, 0, 0, 'R');
	cs := fft->C_from_ints(ints, real s.maxvalue);
	cs.print("x", "y");
	cs.fft(1, sample_power);
	cs.print("f", "a");
	fd := cs.save(nil, fft_dir, start_frame, 0, 0);  # r only !
	if(fd == nil) {
		sys->print("NOT SAVED\n");
	} else {
		sys->print("SAVED\n");
		cs.fft(-1, sample_power);
		cs.print("x'", "y'");
		sys->print("NOW LOAD\n");
		cl := C_from_file("/usr/m/water_fft/100.0-0.fft", 1, 0);
		cl.print("f", "a");
		cl.fft(-1, sample_power);
		cl.print("x", "y");
	}
}

sample_ffts(seq : ref Sequence, s : ref Samples, low_ffts : ref Complexes, low_f, high_f : big, r : real) : (ref Complexes, ref Complexes)
{
	high_ffts : ref Complexes;
	if(high_f == low_f) {
		high_ffts = low_ffts; 
	} else {
		s.advance_to(seq, big high_f);
		high_ffts = fft->C_from_reals(s.in_sequence());
		high_ffts.fft(1, sample_power);
		low_ffts.interpolate(high_ffts, real high_f - r);
	}
	return (low_ffts, high_ffts);
}

pal_to_ntsc(seq : ref Sequence, pal_startframe, pal_endframe : big)
{
	src_fps := 25.0;
	target_fps := 29.97;

	ratio := src_fps / target_fps;

	ntsc_frames := big (ratio *  (real pal_endframe - real pal_startframe));

	ntsc := ref Sequence(0, "/usr/m/water_ntsc", ntsc_frames, seq.width, seq.height, seq.maxvalue, seq.bpp);

	pixel := Pixel(big 0, 0, 0, 0, 0);
	w := chan of ref Pixel;

	spread := big 8;
	midpixel := 4;

	spawn(ppmdv->write_to_pixel(ntsc, w));
	for(pixel.x = 0; pixel.x < seq.width; pixel.x++)
	for(pixel.y = 0; pixel.y < seq.height; pixel.y++)
	for(pixel.channel = 0; pixel.channel < 3; pixel.channel++) {
		pixel.frame = pal_startframe;

		samples := seq.sample_set(pixel.frame - spread, pixel.frame + spread, pixel.x, pixel.y, pixel.channel);
		smp := samples.in_sequence();
		pixel.v = int (real ntsc.maxvalue * smp[midpixel]);
		w <-= ref pixel;

# eliminated for testing
	if(0) {

		low_ffts : ref Complexes;
		result : ref Complexes;
		high_f : big;
		low_f : big;
		for(r := ratio; pixel.frame++ < pal_startframe + ntsc_frames; r += ratio) {
			low_f = big math->floor(r);
			if(low_f != high_f) { 
				samples.advance_to(seq, big low_f);
				low_ffts = fft->C_from_reals(samples.in_sequence());
				low_ffts.fft(1, sample_power);
			}
			high_f = big math->ceil(r);
			(result, low_ffts) = sample_ffts(seq, samples, low_ffts, low_f, high_f, r);
			result.fft(-1, sample_power);
smp = samples.in_sequence();
			pixel.v = int (real seq.maxvalue * smp[midpixel]);
			w <-= ref pixel;
		}
		w <- = nil;
	}
	}
}


init(nil: ref Draw->Context, nil: list of string)
{
	draw = load Draw Draw->PATH;
	sys = load Sys Sys->PATH;
	math = load Math Math->PATH;

	ppmdv = load PPM_dv "../ppm_dv/ppm_dv.dis";
	ppmdv->init(nil, nil);

	sample_power = higher_power(sample_size);

	fft = load FFT "/usr/m/fft/short_fft.dis";
	fft->init(nil, nil);

#	test2();

	s := ppmdv->new_sequence("/usr/m/water_pal");
	s.scan();
	pal_to_ntsc(s, big 100, big 125);
	

#	generate_ffts("/usr/m/water_pal", big 199, big 200);
#	resample("/usr/m/water_pal", big 100, big 125, "/usr/m/water_ntsc", big 100, big 130);

	sys->print("whee\n");
}


# Put	Limbo	ntsc_pal 
#	rm /usr/m/water_fft/*

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].