Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 13th October 2022, 21:58   #1  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
Trying to recreate a composite signal simulation

I've been thinking very much about doing an simulation of an video signal through Composite.

But i will need some help in order to get that done.
If this idea works well, i will try to rewrite DotCrawl++ to use this new script.

First is to create a luma signal.
The luma signal has an checkerboard look (and that's where dotcrawls come from).

I will be very thankfully for the help.

Images from DoctorDothraki's Domesday Duplicator uploads.


__________________
AviSynth+ Projects:
DotCrawl++
RGMOfficial is offline   Reply With Quote
Old 13th October 2022, 23:07   #2  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,041
Luma do not have dotcrawl - it is chroma encoded addition. So to create more or less standard chroma subcarrier data it is required to read documentation and implement colour encoder to target colour system (typically PAL or NTSC) and more or less simply mix to luma data. The full composite encoder may (or typically do) have luma partial suppression filter at chroma band to make cross-distortions less visible. So better composite simulation mixer need also filter luma signal before final output mix.

Signal with checkerboard it is already mixed composite signal (luma +encoded chroma). The PAL/NTSC chroma subcarrier have phase flip to 180degrees (inversion) at each line to make residual distortion (after not ideal luma/chroma separation at decoder) less visible (checkerboard instead of vertical lines).

The sad story about digital processing after composite decoder - the input composite signal may be partially damaged after passing colour decoder (its residual colour subcarrier that cause effect of dotcrawl) so it may be not completely equal to simulated standard composite data. It may have both phase and amplitude errors not present in input composite data and these errors may be unique for each colour decoder implementation. So better way is in that doomsday-duplicator project is full composite colour decoder with dotcrawl effect suppression by single developer - not trying to make addition to (unknown) external decoder.

Last edited by DTL; 13th October 2022 at 23:16.
DTL is offline   Reply With Quote
Old 13th October 2022, 23:10   #3  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
Quote:
Originally Posted by DTL View Post
Luma do not have dotcrawl - it is chroma encoded addition. So to create more or less standard chroma subcarrier data it is required to read documentation and implement colour encoder to target colour system (typically PAL or NTSC) and simply mix to luma data.

Signal with checkerboard it is already mixed composite signal (luma +encoded chroma). The PAL/NTSC chroma subcarrier have phase flip to 180degrees (inversion) at each line to make residual distortion (after not ideal luma/chroma separation at decoder) less visible (checkerboard instead of vertical lines).
Oh. Understand.
Interesting info though.

Let's see. How i can make this chroma addition?
I need to think about it.
__________________
AviSynth+ Projects:
DotCrawl++
RGMOfficial is offline   Reply With Quote
Old 13th October 2022, 23:31   #4  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,041
Take any open documentation on your target colour composite system encoder and make math program to some execution environment.

PAL and NTSC quadrature modulation is simple enough like multiplication and sum of sin() functions. I think most information can be taken from ITU-BT 470 - https://www.itu.int/dms_pubrec/itu-r...1-S!!PDF-E.pdf

For example math equation for chroma signal from 2.9 of Table 2. Also read about phase switching of chroma subcarrier - like 2.16 of Table 2 and may be other notes in that document.
DTL is offline   Reply With Quote
Old 13th October 2022, 23:45   #5  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
Quote:
Originally Posted by DTL View Post
Take any open documentation on your target colour composite system encoder and make math program to some execution environment.

PAL and NTSC quadrature modulation is simple enough like multiplication and sum of sin() functions. I think most information can be taken from ITU-BT 470 - https://www.itu.int/dms_pubrec/itu-r...1-S!!PDF-E.pdf

For example math equation for chroma signal from 2.9 of Table 2. Also read about phase switching of chroma subcarrier - like 2.16 of Table 2 and may be other notes in that document.
Very interesting and helpful.
I will see if i can use math with images on AVS, and then use these equations.
__________________
AviSynth+ Projects:
DotCrawl++
RGMOfficial is offline   Reply With Quote
Old 14th October 2022, 00:17   #6  |  Link
kedautinh12
Registered User
 
Join Date: Jan 2018
Posts: 2,153
If had new ver, can you notification at your doom9 post??
kedautinh12 is offline   Reply With Quote
Old 23rd October 2022, 18:11   #7  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
I'm trying out some way...

Code:
Tweak(hue=44)

Y = ShowY()
I = ShowU()
Q = ShowV()

C = BlankClip(last).mt_lutspa(mode="absolute", chroma="-128", expr=("x 4 % 2 < 0 1 ? y 4 % 2 < 0 1 ? + 1 == 0 255 ?"))

I_luma = ex_lutxy(I,C,"x y - abs")
Q_luma = ex_lutxy(Q,I_luma,"x y - abs")

Y = ex_lutxy(Y,Q_luma,"x y + abs")

return Y
__________________
AviSynth+ Projects:
DotCrawl++

Last edited by RGMOfficial; 23rd October 2022 at 18:12. Reason: Forgot to clear the code a bit
RGMOfficial is offline   Reply With Quote
Old 23rd October 2022, 21:30   #8  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
So what about the chroma signal?
__________________
AviSynth+ Projects:
DotCrawl++
RGMOfficial is offline   Reply With Quote
Old 24th October 2022, 15:48   #9  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
Now, if someone can help fix the chroma issue i had.

(I'm using an DotCrawl++ function for the mults at the moment, but i will change to an original function later)

Code:
function composite_effect(clip clip, float "subcarrier_amplitude"){
    subcarrier_amplitude = Default(subcarrier_amplitude,0.5)
    
    clip.Tweak(hue=44)

    Y = ShowY()
    I = ShowU()
    Q = ShowV()

    ## LUMA SIGNAL (merge information from chroma planes)

    U_C = dcpp_makedotcrawl(2)
    V_C = ex_invert(U_C)

    I_luma = ex_lutxy(I,U_C,"x y - abs "+string(subcarrier_amplitude)+" *")
    Q_luma = ex_lutxy(Q,V_C,"x y - abs "+string(subcarrier_amplitude)+" *")
    
    Y = ex_lutxyz(Y,I_luma,Q_luma,"x y + z + abs "+string(subcarrier_amplitude)+" *")
    
    I = BlankClip(Y)
    Q = BlankClip(Y)

    c = Overlay(BlankClip(Y),Y,x=2)

    sum = ex_lutxy(Y,c,"x y -")

    sum = sum.Overlay(c,mode="add",mask=c,opacity=1).blur(1,0)

    Y = sum.Levels(0,1,128,0,255)
    chroma = ex_lutxy(c,Y,"x y 0.5 * -")

    chroma = invert(chroma)

    chroma = ex_lut(chroma,"x 0.31 * 0.5 /").invert()

    chroma_s1 = Overlay(BlankClip(chroma),chroma,x=2)

    chroma_s3 = Overlay(chroma,chroma,x=2,mask=U_C)
    chroma_s4 = Overlay(chroma,chroma,x=2,mask=V_C)

    I_1 = Overlay(chroma_s3,chroma_s3,x=2,mask=U_C)
    Q_1 = Overlay(chroma_s4,chroma_s4,x=-2,mask=V_C)

    I_2 = Overlay(chroma_s4,chroma_s4,x=-2,mask=U_C)
    Q_2 = Overlay(chroma_s3,chroma_s3,x=2,mask=V_C)

    GScriptClip(last,"""
    #Y = ConditionalSelect(Y, "current_frame % 2",Y,Y_test)
    I = ConditionalSelect(I, "current_frame % 2",I_1,I_2)
    Q = ConditionalSelect(Q, "current_frame % 2",Q_1,Q_2)
    """,local=true)

    I = I_1
    Q = Q_1

    return YToUV(I,Q,Y).Tweak(hue=-44)
    StackHorizontal(last,vid)

    #StackHorizontal(original,chroma)
}
__________________
AviSynth+ Projects:
DotCrawl++
RGMOfficial is offline   Reply With Quote
Old 24th October 2022, 20:45   #10  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,041
After you calculate I and Q chroma signals - you need to quadrature modulate chroma subcarrier and mix (addition) it with your luma data. The composite data is Y-only - not visibly colored. To demodulate it back to coloured you need to process it with composite decoder. I not sure if it is easy to do with AVS scripting only - better with C-program.

Last edited by DTL; 25th October 2022 at 08:01.
DTL is offline   Reply With Quote
Old 25th October 2022, 00:33   #11  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
Quote:
Originally Posted by DTL View Post
After you calculate I and Q chroma signals - you need to quadrature modulate chroma subcarrier and mix (addition) it with your luma data. The composite data is Y-only - not visibly colored. To demodulate it back to coloured youneed to process it with composite decoder. I not sure if it is easy to do with AVS scriptong only - better with C-program.
Ok, so can you show me in C program? Maybe i can translate this code into AviSynth.
__________________
AviSynth+ Projects:
DotCrawl++
RGMOfficial is offline   Reply With Quote
Old 25th October 2022, 08:02   #12  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,041
For software composite demodulator you may look at vhs-decode project https://github.com/oyvindln/vhs-decode . Looks like this file https://github.com/oyvindln/vhs-deco...ode/process.py
DTL is offline   Reply With Quote
Old 4th July 2023, 01:13   #13  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
Ok, so after some comeback, i did made a new version, but still no correct colors. I need help because i can't seem to find what's the issue?

Code:
"your video source"

ConvertToYUV444(interlaced=true,chromaresample="spline64")
Spline64Resize(760-(4+4),height).AddBorders(4,0,4,0)
AddBorders(0,3,0,3)

ConvertBits(16)

CombinePlanes(last,planes="YVU",source_planes="YUV")
Tweak(hue=33)

ex_boxblur(2,0,mode="weighted",Y=1,UV=3)

original = last

## Pattern ##
chk = mt_lutspa(last, mode="absolute", chroma="-128", expr=("x 4 % 2 < 0 1 ? y 4 % 2 < 0 1 ? + 1 == 0 range_max ?")).Invert()
chkInverse = chk.Invert()
chk = Interleave(chk,chkInverse)
chkInverse = chk.Invert()

## Mix into luma ##
function AbsChroma(clip "chan"){
    pos=chan.ColorYUV(off_y=-128)
    neg=Invert(chan).ColorYUV(off_y=-128)
    
    return Overlay(pos,neg,mode="Add")
}
function AbsChromaAdd(clip "chan"){
    pos=chan.ColorYUV(off_y=-128)
    neg=Invert(chan).ColorYUV(off_y=-128)
    
    return Overlay(pos,neg,mode="Subtract")
}

chr = ex_lutxy(ExtractU(original),chk.ExtractY(),"x y range_max / *")
chr = ex_lutxyz(chr,ExtractV(original),chkInverse.ExtractY(),"x y z range_max / * +")

chr = chr.AbsChroma()

ex_lutxy(ExtractY(original),chr,"x y +")

## Separate chroma from luma ##
Y = last.SeparateFields().F2Quiver(1,1,128,255,0).Weave()

chroma = ex_lutxy(last,Y,"x y -").ColorYUV(off_y=128)

U = Overlay(chroma,chroma,x=2,mask=chk)
V = Overlay(chroma,chroma,x=2,mode="add",opacity=.5,mask=chkInverse)

## Join planes into one colored clip ##
final = CombinePlanes(Y,U,V,planes="YUV",source_planes="YYY",sample_clip=original)
final = final.Tweak(hue=-33).CombinePlanes(planes="YVU",source_planes="YUV")
return final
__________________
AviSynth+ Projects:
DotCrawl++
RGMOfficial is offline   Reply With Quote
Old 4th July 2023, 15:56   #14  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 2,352
For modulation and demodulation you have to rotate the signal 90º, for that you use sin and cos, for QAM specifically read over here.
__________________
i7-4790K@Stock::GTX 1070] AviSynth+ filters and mods on GitHub + Discussion thread
Dogway is offline   Reply With Quote
Old 4th July 2023, 16:14   #15  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
Quote:
Originally Posted by Dogway View Post
For modulation and demodulation you have to rotate the signal 90º, for that you use sin and cos, for QAM specifically read over here.
Can you show how i can do that in something like lutspa or lutxy?
__________________
AviSynth+ Projects:
DotCrawl++
RGMOfficial is offline   Reply With Quote
Old 4th July 2023, 18:29   #16  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 2,352
You have an example here or this one. Just mind you the YIQ model was only used up to 1979, since then YUV (not YCbCr) was used for all regions.

If you want to know the exact figures check this file where I researched most of them.
__________________
i7-4790K@Stock::GTX 1070] AviSynth+ filters and mods on GitHub + Discussion thread
Dogway is offline   Reply With Quote
Old 4th July 2023, 19:11   #17  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
Quote:
Originally Posted by Dogway View Post
You have an example here or this one. Just mind you the YIQ model was only used up to 1979, since then YUV (not YCbCr) was used for all regions.

If you want to know the exact figures check this file where I researched most of them.
Ok, so... i did try my best to convert into RPN.

Code:
I = ex_lutxy(ExtractU(original),ExtractV(original), "y range_half - 0.83867057 * x range_half - 0.54463904 * - range_half +")
Q = ex_lutxy(ExtractU(original),ExtractV(original), "y range_half - 0.54463904 * x range_half - 0.83867057 * + range_half +")

chromaModFreq = (4.0 * Pi() / 15.0)

expr = ("pi x + y 2 % frameno + + "+string(chromaModFreq)+" *")

chkI = ex_lutspa(BlankClip(last),mode="absolute",expr=expr+" sin").extracty()
chkI = ex_lutxy(I,chkI,"x y *")
chkQ = ex_lutspa(BlankClip(last),mode="absolute",expr=expr+" cos").extracty()
chkQ = ex_lutxy(Q,chkQ,"x y *")
return chkQ.Subtitle(mt_infix(expr))
__________________
AviSynth+ Projects:
DotCrawl++
RGMOfficial is offline   Reply With Quote
Old 4th July 2023, 19:32   #18  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 2,352
I guess it's right? You can try to demodulate it to check if it passes the roundtrip test. The Crosstalk matrix is defined here depending if you want composite or s-video.

EDIT: I updated my figures since I just read in the Wiki for YIQ that YUV required equal bandwidths, so that's a hint to know whether YIQ or YUV was used.

EDIT2: Currently you are using YUV to YIQ coefficients, but if I'm not wrong your source is in YCbCr not YUV. So you either use YCbCr->YUV->YIQ coefficients for very old composite signals, or simply use YCbCr->YUV coefficients.

YCbCr->YUV
Code:
Cb->U = 0.435812284313725 / 0.5 = 0.87162456862745
Cr->V = 0.615857694117647 / 0.5 = 1.231715388235294
YCbCr->YUV->YIQ
Code:
Cb->I = 0.871624568627450 * sin(33) = 0.474720768297668
Cb->Q = 0.871624568627450 * cos(33) = 0.731005873796788
Cr->I = 1.231715388235294 * cos(33) = 1.033003446729065
Cr->Q = 1.231715388235294 * sin(33) = 0.670840286601698

Here are all the conversion matrices, you can test them with MatrixClip() using switch=true when RGB is included:

Code:
toRad = 33*(pi/180)
YUVtoYIQ = [1.0,  0.00000000, 0.00000000,\
            0.0, -sin(toRad), cos(toRad),\
            0.0,  cos(toRad), sin(toRad)]
Chroma range (±0.435812284313725,±0.615857694117647)
Code:
RGBtoYUV = [0.298912, -0.147111592156863,  0.615857694117647,\
            0.586603, -0.288700692156863, -0.515290478431373,\
            0.114485,  0.435812284313725, -0.100567215686275]
Chroma range (±0.59662443399429320,±0.52277213335037230)
Code:
RGBtoYIQ = [0.298912,  0.59662443399429320,  0.21204200387001038,\
            0.586603, -0.27492129802703860, -0.52277213335037230,\
            0.114485, -0.32170313596725464,  0.31073009967803955]
Code:
YCCtoYUV = [1.0,  0.000000000000000, 0.000000000000000,\
            0.0,  0.871624568627450, 0.000000000000000,\
            0.0,  0.000000000000000, 1.231715388235294]
Code:
YCCtoYIQ = [1.0,  0.0000000000000000, 0.0000000000000000,\
            0.0, -0.4747207760810852, 0.7310058474540710,\
            0.0,  1.0330034494400024, 0.6708403229713440]
__________________
i7-4790K@Stock::GTX 1070] AviSynth+ filters and mods on GitHub + Discussion thread

Last edited by Dogway; 6th July 2023 at 18:41.
Dogway is offline   Reply With Quote
Old 5th July 2023, 18:26   #19  |  Link
RGMOfficial
Registered User
 
RGMOfficial's Avatar
 
Join Date: May 2022
Location: Brazil
Posts: 38
Quote:
Originally Posted by Dogway View Post
I guess it's right? You can try to demodulate it to check if it passes the roundtrip test. The Crosstalk matrix is defined here depending if you want composite or s-video.

EDIT: I updated my figures since I just read in the Wiki for YIQ that YUV required equal bandwidths, so that's a hint to know whether YIQ or YUV was used.

EDIT2: Currently you are using YUV to YIQ coefficients, but if I'm not wrong your source is in YCbCr not YUV. So you either use YCbCr->YUV->YIQ coefficients for very old composite signals, or simply use YCbCr->YUV coefficients.

YCbCr->YUV
Code:
Cb->U = 0.435812284313725 / 0.5 = 0.87162456862745
Cr->V = 0.615857694117647 / 0.5 = 1.231715388235294
YCbCr->YUV->YIQ
Code:
Cb->I = 0.871624568627450 * 0.83867057 = 0.731005873796788
Cb->Q = 0.871624568627450 * 0.54463904 = 0.474720768297668
Cr->I = 1.231715388235294 * 0.83867057 = 1.033003446729065
Cr->Q = 1.231715388235294 * 0.54463904 = 0.670840286601698

Here are all the conversion matrices, you can test them with MatrixClip() using switch=true when RGB is included:

Code:
YUVtoYIQ = [1.0,  0.00000, 0.00000,\
            0.0, -sin(33), cos(33),\
            0.0,  cos(33), sin(33)]
Code:
RGBtoYUV = [0.298912, -0.147111592156863, 0.615857694117647,\
            0.586603, -0.288700692156863,-0.515290478431373,\
            0.114485,  0.435812284313725,-0.100567215686275]
Code:
RGBtoYIQ = [0.298912,  0.13892203569412231,  0.61775660514831540,\
            0.586603,  0.29551663994789124, -0.51141208410263060,\
            0.114485, -0.43443867564201355, -0.10634452104568481]
Code:
YCCtoYUV = [1.0,  0.000000000000000, 0.000000000000000,\
            0.0,  0.871624568627450, 0.000000000000000,\
            0.0,  0.000000000000000, 1.231715388235294]
Code:
YCCtoYIQ = [1.0,  0.000000000000000000,  0.000000000000000000,\
            0.0, -0.871547758579254200, -0.011572339572012424,\
            0.0, -0.016353175044059753,  1.231606841087341300]
Ok. YUV to YIQ is okay, but still the encoding is not what i expected (the expected is being an checkerboard-sine-wave-like pattern, following QAM).

Code:
YUVtoYIQ = [1.0,  0.00000, 0.00000, 0.0, -sin(33), cos(33), 0.0,  cos(33), sin(33)]

I = ExtractU(MatrixClip(original,YUVtoYIQ,switch=false))
Q = ExtractV(MatrixClip(original,YUVtoYIQ,switch=false))

chromaModFreq = (4.0 * Pi() / 15.0)

expr = ("pi x + y 2 % frameno + + "+string(chromaModFreq)+" *")

chkIm = ex_lutspa(BlankClip(last),mode="absolute",expr=expr+" sin").extracty()
chkI = ex_lutxy(I,chkIm,"x y *")
chkQm = ex_lutspa(BlankClip(last),mode="absolute",expr=expr+" cos").extracty()
chkQ = ex_lutxy(Q,chkQm,"x y *")

chr = Overlay(BlankClip(original).extracty(),chkI,mode="add")
chr = Overlay(chr,chkQ,mode="add")

return ex_lutxy(ExtractY(original),chr,"x y +").Subtitle(mt_infix(expr))
__________________
AviSynth+ Projects:
DotCrawl++
RGMOfficial is offline   Reply With Quote
Old 6th July 2023, 04:36   #20  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 2,352
First of all, sorry for the wrong figures since the YUVtoYIQ is wrong in many places, including the Wikipedia. I double checked and added the proper derivations. The post above was edited with the correct matrices for XXXtoYIQ. Soon I will add these to TransformsPack - Models

With that said, the way to convert YCbCr to YIQ is as follows:

Code:
YCbCr source

ConvertToYUV444(chromaresample="spline16")
ConvertBits(32,fulld=true)

MatrixClip(YCCtoYIQ, switch=false)
ConvertBits(8,dither=1)

# Now decide what you want to do with Luma, full or narrow range?

I = ExtractU()
Q = ExtractV()
__________________
i7-4790K@Stock::GTX 1070] AviSynth+ filters and mods on GitHub + Discussion thread

Last edited by Dogway; 6th July 2023 at 04:38.
Dogway is offline   Reply With Quote
Reply

Tags
composite, ntsc, simulation

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 11:08.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.