NTSC encoding/decoding in C89 using only integers and fixed point math
github.com
github.com
(Fun facts: Because of that, countries with PAL instead of NTSC never knew what a "tint control" on the TV was, and the nostalgic 80s VHS look is also missing that blueish/purple color shift there.)
I wrote both an NTSC+PAL decoder in Matlab, and a PAL encoder in an FPGA (also fixed point), which I use in an actual project as composite video output. Decoders are harder and less straightforward than encoders, with lots of optimizing potential, because you need to filter the color signal out (I look forward to seeing what this code did). If you really, truly understand how NTSC and PAL work in their mathematical details, you may get your mind blown away by reading about this decoder, which is likely the best PAL decoder that ever existed: http://www.jim-easterbrook.me.uk/pal/
Writing my own encoder and decoder was super enlightening, and there are tons of details to nerd out on, e.g. when you get into data that's encoded into the sync gap for Videotext, closed captions, and other stuff.
PAL fixed it by flipping the phase around every line. By subtracting the current line from the previous line, the phase error would cancel out (but is also more expensive since you need to remember the last line, in a delay line or memory[1]). So, always the same color. (But not ATSC, that's something else entirely...)
[1] Well, there wer supposedly "PAL simple" receivers in the very beginning, where no processing of the phase flip was done and your eye was supposed to average the difference out. Probably looked terrible unless you were sitting really far away...
There simply wasn’t a better option, at the time. Both options were engineered with limited resources to best fit their respective needs. NTSC had a better refresh rate and easier hardware integration, plus 70+ years of backwards/forwards compatibility (a 1941 NTSC B+W television set could be used to watch the series finale of Friends in 2004 using a bog standard antenna for over the air signals); PAL had almost 30 years of experience and fixed some of the major issues with NTSC (primarily the Phase signaling) and had increased resolution at the cost of refresh rates.
Both were pushing analog transmission bandwidth to the limits and did admirably until digital options were available and became the norm.
If only digital could be used for 99% of distribution, with OTA still being at least some sort of hybrid system for better resilience. Digital broadcasting has very low resilience to interference. Speaking from a US perspective here, where we got saddled with 8VSB (from my understanding, COFDM is much more resilient).
In an analog signal, a bright picture will be 700mV, a less bright picture will be 500mV, a dark one at 200mV and a very dark one at 50mV.
Imagine that you get a 300mV error, that loses a lot of data - the dark one will be sort of bright, or vice versa, or the sort-of bright will be really-bright, etc.
Now lets say you have a 1 represented by an amplitude of 700mV, and a 0 represented by 50mV. A 300mV error wlll have it at 400mV and 350mV. Your system will go "hey this is 350mV, it's a zero", and reclock it to 50mV, and vice versa. The recovered signal will be identical upto the point that the errors flip the bits - the digital cliff.
(In reality of course the signal isn't just high/low but uses various techniques to encode the ones and zeros to prevent DC voltages accruing - Manchester Encoding for example.
Push an analog video signal down a cable and it will degrade the longer the cable is. The same will happen in the digital domain -- you can see this on a waveform monitor by looking at the digital eye, but as long as the eye is open enough the signal can be retrieved to it's original state. With an analog signal, the signal is lost, and can't be retrieved.
The only Blu-ray I had lying around was Back to the Future II, so that's what I used. Here is one of the very first pictures from my decoder, you can see dot crawl artifacts all over the place from my shoddy filtering (if I filtered at all at that stage): https://i.imgur.com/k2ZiCrH.png
You can also see the insanely overkill sample rate I used (whatever my oscilloscope was set to, it could do 300MHz) by the numbers on the bottom. That's horizontal resolution, as sampled. But you won't get more than at most ~700 really discernible pixels with SD composite video's bandwidth.
Finally, this picture shows everything: The (green) color burst on the left, the data in the sync gap at the top, and the vsync pulses at the bottom.
Or maybe the video output from a terminator robot being sent back to the future (pun intended) me in my evil lair.
It has this unreal retro future feel that I’m struggling to put my finger on.
This whole thread was fascinating as well.
There was also a third color modulation scheme, SECAM, which was very different from NTSC/PAL (PAL is really just "NTSC 2.0"). It added the two color signals using plain FM. When degrading, it gave rise to something sometimes called "SECAM fire", and anyone who spent some time in France back then, me included, might subconsciously remember it: https://www.scheida.at/scheida/TV_SEITE/SECAM_Screenshot_Sec... http://www.scheida.at/scheida/TV_SEITE/SECAM_Screenshot_Seca... (Those pictures are not from me, just found on the Internet.)
To the casual onlooker that probably just looks like noisy pictures, what's the big deal... But to me it's interesting because the noise is different.
[1] Of course, my picture is not a bad transmission, just bad decoding.
I wrote my own decoder in python (nowhere near realtime) because at the time I couldn't find one that handled color. The deep dive on the design tradeoffs and signal processing hacks for NTSC was fascinating.
A few of my exploits below:
Full-frame decode of VHS w/ closed captioning: https://mrgris.com/a/ntsc-cc.mp4
Faithful reproduction of analog artifacts: https://mrgris.com/a/colorbars_slow.gif
Analog scrambling: https://www.youtube.com/watch?v=qceZgxSBHwo
Inject custom captions (it supports color!): https://mrgris.com/a/thanks.mp4
Sad that these signals are gone now... would have loved to play around with SAP/MTS, teletext, C-band...
I share the sadness about those signals being effectively gone. How fun it would have been to work with real live broadcast ones at their heyday. There still are a few ones, but they're mostly pretty basic now.
Really cool, mind-blowing stuff. I think this guy is one of the few people in the world creating the software for that specific content creation pipeline.
He's got the exact MIDI style down and everything.
4. No languages used besides C."
I think you just lost >80% of HN readers. No npm install, no Rust, no Go WTF!!! /s
I do love defined challenges like this though. It's amazing what you can learn when DIY vs using someone else's.
It might be interesting to do a survey of OSes and pick carefully. I think Amigas were used to do TV work back in the day...
Edit: By CRT I meant just any monitor with RCA composite video input compared to a monitor with a VGA type input.
Edit2: remembered the name of the card the "PAR" (personal animation recorder). This site has some info on several of the boards including the PAR: https://shop.myamigashop.com/blogs/blogs/information-page-fo...
I'm not sure I'd agree with either, as I don't recall the Amiga having Genlock abilities at all. Only 3rd party expansion cards gave the Amiga the ability to Genlock to external video sources so that it was in sync with the rest of the house. For proper Genlock, you have to have some sort of input (typically a black video signal) to use as a sync source, and I just don't recall an Amiga natively having any kind on input like that.
Without that you'd need an external framebuffer like an infinite window TBC, which is much more expensive.
[1] ERSY mode: http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_gui...
https://retrocomputing.stackexchange.com/questions/22320/wha...
"Just for fun."
Often in DSP, there is just no good reason to use floating point instead of fixed point integers.
The following link is an example of a good quality fixed point math library and shows you how it is done.
https://pkg.go.dev/github.com/shopspring/decimal?utm_source=...
Back in the day, this was the case for the ARMv5 CPUs used by a major phone manufacturer and the software JPEG decoder couldn’t use floats. IIRC you only really needed them when doing YUV -> RGB conversions, so that was all done through integer arithmetic instead.
So your terminal looks like snowy channel 3. Fun!
I notice these effects in videos of real old CRTs and my own old CRT systems.
Languages are not dialects, even in computing.
This is mainly for decoding the composite video signal generated by a computer or console. For example, the NES generates a 12-step square wave for its video output, and you'd decode that to YIQ then convert that to RGB.
Cool I guess.
usage: ./a.out -m|o|f|p|h outwidth outheight noise infile outfile
sample usage: ./a.out -op 640 480 24 in.ppm out.ppm
sample usage: ./a.out - 832 624 0 in.ppm out.ppm
-- NOTE: the - after the program name is required
------------------------------------------------------------
m : monochrome
o : do not prompt when overwriting files
f : odd field (only meaningful in progressive mode)
p : progressive scan (rather than interlaced)
h : print helpwait...
(irony...)