Biên độ tối ưu của một


7

Một hình sin thời gian liên tục có biên độ thực từ 0 đến cực đại A2m10.5 (ví dụ: cho m=16, A32767.5) được lượng tử hóa để mđộ phân giải -bit bằng cách làm tròn nó đến số nguyên gần nhất (Hình 1). Biên độ tối ưu cho khác nhau là gìm24?

nhập mô tả hình ảnh ở đây
Hình 1. Dành cho m=4, một hình sin có biên độ cực đại cho phép A=7.5 (đường liền nét màu xanh), lượng tử hóa của nó (đường đứt nét màu cam) và các số nguyên bổ sung 4 bit hai cực âm và dương nhất có ký hiệu -8 và 7 (màu vàng).

Một câu trả lời là mong muốn cho mỗi trong hai định nghĩa thay thế về sự tối ưu:

  1. tối đa hóa tỷ lệ tín hiệu / nhiễu (SNR), trong đó tín hiệu là hình sin ban đầu và nhiễu là lỗi lượng tử hóa, và
  2. giảm thiểu tổng méo sóng hài (THD), được chuẩn hóa theo biên độ của tần số cơ bản trong chuỗi Fourier của hình sin được lượng tử hóa.

Chào ! Ok vì vậy bây giờ tôi thấy một lý do tại sao bạn quan tâm đến tính toán cực kỳ chính xác của sai số lượng tử thứ 5 và thứ 7 khi đầu vào là một hình sin thuần túy lý tưởng ... ;-) Tôi nghĩ bạn phải nói điều gì đó về chiến lược lấy mẫu đang được sử dụng?
Fat32

1
@ Fat32 Nó giống như câu chuyện với laser. Không có mẫu ở đây. Liệu sự tối ưu theo một trong hai tiêu chí sẽ được đưa đến một kịch bản lấy mẫu cụ thể hay không là một câu hỏi thú vị. Ví dụ, với lấy mẫu ngẫu nhiên, tối ưu bằng def. 1 sẽ được duy trì. Với def. 2, có lẽ lỗi bình phương trung bình gốc liên quan đếnB xấp xỉ một hình sin của biên độ B sẽ được giảm thiểu bằng cách định lượng một hình sin có biên độ tối ưu A. Nhưng tôi không chắc lắm.
Olli Niemitalo

1
Tôi vẫn không hoàn toàn hiểu được những gì bạn đang cố gắng thực hiện ở đây: Bạn định lượng một sóng hình sin liên tục. Đây có phải là bộ lượng tử đồng nhất hay bạn có thể sử dụng bộ lượng tử tối ưu? Nếu nó đồng nhất: bạn chỉ cần dịch chuyển lưới lượng tử hóa lên và xuống trên sóng hình sin để tìm mức tối ưu? Nếu đúng thì tại sao? Điều này sẽ chỉ làm cho sự khác biệt cực kỳ nhỏ.
Hilmar

1
Cảm ơn, điều đó giúp. Vì vậy, bạn không dịch chuyển lưới, bạn đang kéo căng nó (hoặc giữ cho gird không đổi và kéo dài sóng hình sin, điều tương tự). Một câu hỏi nữa nếu tôi có thể: vì tín hiệu là định kỳ nên sẽ là nhiễu lượng tử hóa. Sự khác biệt giữa tiếng ồn RMS và THD là gì? Có nên giống nhau hơn có lẽ là TDH không bao gồm lỗi lượng tử hóa ở mức cơ bản?
Hilmar

1
oh không có lấy mẫu, chỉ là lượng tử hóa dạng sóng. Tôi nghĩ rằng những cuốn sách sau đây sẽ hữu ích cho phân tích toàn diện của bạn về lượng tử hóa: Lượng tử hóa_B.Widrow và Lượng tử hóa vectơ và nén tín hiệu_Gersho & Gray ... Như bạn cũng biết, lượng tử hóa được xem chủ yếu từ góc độ thống kê cho mục đích mã hóa nguồn, chưa từng thấy loại tối ưu hóa này nhưng tôi nghĩ nó cũng có thể có một số ý nghĩa hay ...
Fat32

Câu trả lời:


4

Pha của hình sin không quan trọng: Sự dịch pha của hình sin tương đương với việc dịch chuyển nó theo thời gian, dẫn đến sự dịch chuyển thời gian của cả hình sin được lượng tử hóa và lỗi lượng tử hóa. Phổ công suất là bất biến đối với sự dịch chuyển thời gian . Chúng tôi chọn làm việc với hình sinAcos(x).

Tối ưu bởi def. 1

Tương đương với tối đa hóa tỷ lệ nhiễu tín hiệu (SNR), chúng ta có thể giảm thiểu lỗi lượng tử hóa bình phương trung bình gốc so với bình phương trung bình gốc 1/2A của hình sin, RRMSE = 1/SNR. Việc phân tích trong quý đầu tiên của sóng cosin là đủ, bởi vì phần còn lại của cả sóng cosin và lỗi lượng tử hóa đều giống hệt với quý đầu tiên của chúng cho đến khi lật dấu và / hoặc đảo ngược thời gian. Để chox trong quý đầu tiên của làn sóng cosin, 0<x<π/2. Dọc các dòng của phương trình. 2 câu trả lời của tôi cho một câu hỏi liên quan , sóng cosin lượng tử đạt được một giá trị nguyênk0round(A) khi nào:

(1)0<x<acos(round(A)0.5A),if k=round(A),acos(k+0.5A)<x<acos(k0.5A),if 1kround(A)1,acos(0.5A)<x<π2,if k=0.

Mỗi giá trị của k đưa ra lỗi bình phương trung bình tương đối RelMSE một đóng góp phụ gia của:

(2)2MSEkA2=2A21π/2x0x1(Acos(x)k)2dx=2sin(x1)cos(x1)2sin(x0)cos(x0)π+8k(sin(x0)sin(x1))πA+4k2(x1x0)πA2+2x12x0π,

Ở đâu x0x1 biểu thị, như được định nghĩa riêng cho từng k, giới hạn x0<x<x1được đưa ra bởi phương trình. 1. Tổng số lỗi lượng tử trung bình bình phương tương đối là:

(3)RelMSE=2MSEA2=k=0round(A)2MSEkA2=2asin(12A)π4A212πA2(2A2+4round(A)2)asin(2round(A)12A)πA2(6round(A)+1)4A2(2round(A)1)22π(A2+2round(A)2)2πA2+1πA2k=1round(A)1((2A2+4k2)(asin(2k+12A)asin(2k12A))+(6k1)4A2(2k+1)2(6k+1)4A2(2k1)22),A>0.5.

Để tối ưu theo định nghĩa 1, nhiệm vụ là tìm giá trị của A mà giảm thiểu các lỗi lượng tử trung bình bình phương gốc tương đối RRMSE =RelMSE. dưới sự ràng buộcA2m10.5. Phương trình 3 có thể được đánh giá bằng Python bằng mpmaththư viện chính xác tùy ý:

import mpmath as mp
def RelMSE(A):  # valid for A >= 0.5
    A = mp.mpf(A)
    return 2*mp.asin(1/(2*A))/mp.pi - mp.sqrt(4*A**2-1)/(2*mp.pi*A**2) - (2*A**2 + 4*mp.floor(A + 0.5)**2)*mp.asin((2*mp.floor(A + 0.5) - 1)/(2*A))/(mp.pi*A**2) - ((6*mp.floor(A + 0.5) + 1)*mp.sqrt(4*A**2 - (2*mp.floor(A + 0.5) - 1)**2) - 2*mp.pi*(A**2 + 2*mp.floor(A + 0.5)**2))/(2*mp.pi*A**2) + mp.nsum(lambda k: (2*A**2 + 4*k**2)*(mp.asin((2*k+1)/(2*A)) - mp.asin((2*k-1)/(2*A))) + ((6*k-1)*mp.sqrt(4*A**2 - (2*k + 1)**2) - (6*k + 1)*mp.sqrt(4*A**2 - (2*k - 1)**2))/2, [1, mp.floor(A + 0.5)-1])/(mp.pi*A**2)

RRMSE dường như có tối thiểu cục bộ giữa mỗi cặp số nguyên liên tiếp A (Hình 1).

enter image description here
Hình 1. RRMSE (đường liền nét màu xanh và hình vuông màu xanh) và xấp xỉ của nó 1/6/A (đường đứt nét màu cam) dựa trên phương sai 1/12 phân bố đồng đều chiều rộng 1, cho các phạm vi khác nhau của A.

Một lựa chọn tối ưu A được đưa ra trong Bảng 1 cùng với RRMSE kết quả, cũng cho một số giá trị phổ biến khác của A. Tại lớn hơnm, RRMSE giảm bởi sự lựa chọn tối ưu sẽ là cận biên. Các mục trong bảng, chỉ hiển thị các chữ số bằng nhau giữa hai tính toán sử dụng các cài đặt độ chính xác khác nhau, có thể được tạo bởi tập lệnh Python sau (tiếp theo), quá trình thực hiện mất nhiều ngày:

def approx_optimal_A(m):
    m = mp.mpf(m)
    return 2**(m-1) - 1 + mp.mpf("0.156936321399") + mp.exp(-1.2749819017 - 0.3464088917*m)  # Eq. 8
    # return 2**(m-1) - 1  # This less informed guess gives identical results but slower convergence

def to_max_digits(f, prec_1, prec_2, max_digits):  # return the at most max_digits digits of function f that are agreed about by both precision settings
    prec = mp.mp.prec
    mp.mp.prec = prec_1
    y_prec_1 = f()
    mp.mp.prec = prec_2
    y_prec_2 = f()
    digits = max_digits
    while mp.nstr(y_prec_1, digits, strip_zeros=False) != mp.nstr(y_prec_2, digits, strip_zeros=False):  # Beware: a possible infinite loop
        digits -= 1
    return mp.nstr(y_prec_2, digits, strip_zeros=False)
    prec = mp.mp.prec

double_digits = 15  # Print at most this many digits
dB_digits = 9

for m in range(2, 25):
    optimal_A = to_max_digits(lambda: mp.findroot(lambda A: mp.diff(RelMSE, A), approx_optimal_A(m)), 80, 100, double_digits)
    RelMSE_optimal = to_max_digits(lambda: 10*mp.log10(RelMSE(mp.mpf(optimal_A))), 80, 100, dB_digits)
    RelMSE_1 = to_max_digits(lambda: 10*mp.log10(RelMSE(2**(m-1)-1)), 80, 100, dB_digits)
    RelMSE_2 = to_max_digits(lambda: 10*mp.log10(RelMSE(2**(m-1)-0.5)), 80, 100, dB_digits)
    print(str(m)+"&"+optimal_A+"&"+RelMSE_optimal+"&"+RelMSE_1+"&"+RelMSE_2+"\\\\")

Bảng 1. Tối ưu A theo định nghĩa 1 cho khác nhau m24 và RRMSE kết quả, với RRMSE cho một số lựa chọn phổ biến của A liệt kê để so sánh. m=1đã bị loại bỏ bởi vì nó không thể được xử lý bởi phương trình. 3 và bởi vì một bit đơn không biểu thị bất kỳ số dương nào dưới dạng đại diện bổ sung của hai. Lưu ý rằng RRMSE tính theo dB được chuyển đổi thành SNR theo dB bằng cách lật dấu, bởi vìSNR = 1/RelMSE = 1/RRMSE2.

moptimal ARRMSE (dB)A=optimal2m112m10.521.2682794946153011.11280538.9272980510.176464533.2380094212103718.820693717.958886317.888200447.2165859792940725.516767325.090304824.7375654515.200718133195531.812709431.577553731.2013629631.188875671425737.936488037.797788337.4726954763.180083539419043.985891043.900111443.64143088127.17361362552350.004951849.950005349.75278179255.16889473636156.013474355.977338255.830720010511.16547918889062.020002261.995763861.8884975111023.1630220537768.027866168.011368967.9337180122047.1612626448474.038059074.026709573.9708981134095.1600072251680.050595880.042726780.0028089148191.1591137160186.065140986.059654186.03120091516383.158478966692.081282292.077441092.05720791632767.158028642898.098640798.095943798.08157981765535.1577094659104.116904104.115007104.10482118131071.157483397110.135830110.134493110.12727619262143.157323352116.155234116.154291116.14918120524287.157210089122.174984122.174318122.170701211048575.15712995128.194979128.194509128.191950222097151.15707326134.215150134.214818134.213008234194303.15703317140.235446140.23521140.233931248388607.15700481146.255831146.2557146.25476

Tối ưu bởi def. 2

Một hàm tuần hoàn như một hình sin được lượng tử hóa có một chuỗi Fourier; nó là tổng của các sin sin điều hòa, nghĩa là các sin của các tần số hài của tần số cơ bản. Sin sinids hài hòa là trực giao. Do đó, bình phương trung bình của hàm tuần hoàn bằng tổng bình phương trung bình của các sin sin điều hòa. Bình phương trung bình của tổng các hài không cơ bản sau đó có thể được tính bằng cách trừ bình phương trung bình của cơ bản khỏi bình phương trung bình của hàm tuần hoàn. Đối với sóng cosin lượng tử hóaround(Acos(x)) điều này cho phép tính tổng méo hài (THD) là:

(4)THD=MSa12/2a12/2=MSa12/21,

where MS is the mean square of the quantized cosine wave, a12/2 is the mean square of the fundamental, and a1 is the coefficient of the fundamental frequency cosine in the Fourier series of round(Acos(x)), calculated using Eq. 3 of my answer to a related question and simplifying to:

(5)a1=2πA(round(A)4A2(2round(A)1)2+k=1round(A)1k(4A2(2k1)24A2(2k+1)2)).

Mean square of the quantized cosine wave is calculated in its first quarter-period by:

(6)MS=1π/20π/2round(Acos(x))2dx=round(A)2π/2acos(round(A)0.5A)+1π/2k=1round(A)1k2(acos(k0.5A)acos(k+0.5A))

THD is calculated and minimized by the following Python script (continued), using Eqs. 4, 5, and 6:

def a_1(A):
    A = mp.mpf(A)
    return 2*(mp.floor(A + 0.5)*mp.sqrt(4*A**2 - (2*mp.floor(A + 0.5) - 1)**2) + mp.nsum(lambda k: k*(mp.sqrt(4*A**2 - (2*k - 1)**2)-mp.sqrt(4*A**2 - (2*k + 1)**2)), [1, mp.floor(A + 0.5) - 1]))/(mp.pi*A)

def MS(A):
    A = mp.mpf(A)
    return mp.floor(A + 0.5)**2*mp.acos((mp.floor(A + 0.5)-0.5)/A)/(mp.pi/2) + mp.nsum(lambda k: k**2*(mp.acos((k - 0.5)/A) - mp.acos((k + 0.5)/A)), [1, mp.floor(A + 0.5) - 1])/(mp.pi/2)

def STHD(A):  # Square of THD
    MS_1 = a_1(A)**2/2
    return MS(A)/MS_1 - 1

for m in range(2, 25):
    optimal_A = to_max_digits(lambda: mp.findroot(lambda A: mp.diff(STHD, A), approx_optimal_A(m)), 80, 100, double_digits)
    B = to_max_digits(lambda: a_1(mp.mpf(optimal_A)), 80, 100, double_digits)
    THD_optimal = to_max_digits(lambda: 10*mp.log10(STHD(mp.mpf(optimal_A))), 80, 100, dB_digits)
    THD_1 = to_max_digits(lambda: 10*mp.log10(STHD(2**(m-1)-1)), 80, 100, dB_digits)
    THD_2 = to_max_digits(lambda: 10*mp.log10(STHD(2**(m-1)-0.5)), 80, 100, dB_digits)
    print(str(m)+"&"+optimal_A+"&"+B+"&"+THD_optimal+"&"+THD_1+"&"+THD_2+"\\\\")

enter image description here
Figure 2. THD (dB) as function of unquantized amplitude A. The local maxima are at amplitudes that cause a narrow protrusion to poke out at the extrema of the quantized sinusoid.

enter image description here
Figure 3. Amplitude a1 (blue solid line) of the fundamental frequency in the quantization of a cosine wave of amplitude A, with the identity line (orange dashed line) plotted for reference.

Table 2. Optimal A by definition 2 for different m24 and the resulting THD, with the THD for some common choices of A listed for comparison. Surprisingly, THD is minimized by the same A that maximize SNR (Table 1), also when tested with much higher precision than what is shown here. If the signal is considered to be a sinusoid of amplitude a1 instead of amplitude A, then SNR values are obtained by flipping the sign of the THD values.

moptimal Aa1THD (dB)A=optimalA=optimal2m112m10.521.268279494615301.1701195194867910.762957810.149207810.572856233.238009421210373.1955270514517118.763337618.253398018.337009447.216585979294077.1963252507877625.504557325.189554925.0267366515.200718133195515.190704465809031.809847531.615956331.3681507631.188875671425731.183859747699637.935789437.813812237.5642711763.180083539419063.177560110388543.985717543.907130643.69027098127.173613625523127.17234333857750.004908449.953187749.77833449255.168894736361255.16825576659856.013463455.978818455.843912710511.165479188890511.16515814729862.019999461.996465661.8952456111023.163022053771023.1628609305268.027865468.011706467.9371468122047.161262644842047.1611818569774.038058874.026873673.9726322134095.160007225164095.1599667478880.050595880.042807180.0036830148191.159113716018191.1590934470686.065140986.059693786.03164051516383.158478966616383.158468821292.081282292.077460692.05742861632767.158028642832767.158023566298.098640798.095953498.08169051765535.157709465965535.1577069262104.116904104.115011104.10487718131071.157483397131071.157482127110.135830110.134495110.12730419262143.157323352262143.157322717116.155234116.154293116.14919520524287.157210089524287.157209771122.174984122.174319122.170708211048575.157129951048575.15712979128.194979128.194509128.191953222097151.157073262097151.15707318134.215150134.21482134.213010234194303.157033174194303.15703313140.235446140.235212140.233932248388607.157004818388607.15700479146.25583146.25567146.25476

The equivalence of the two optimality definitions holds even when numerical precision is increased significantly, here with m=4 at least to 200 decimal places, in Python (continued):

m = 4
mp.mp.dps = 200
mp.findroot(lambda A: mp.diff(RelMSE, A), 2**(m-1)-1+0.157)
mp.findroot(lambda A: mp.diff(STHD, A), 2**(m-1)-1+0.157)

which outputs numerically identical optimal values for A for the two optimality definitions:

mpf('7.21658597929406951556806247230383254685067097032105786583650636819627678717747461433940963299310318715204551609940031954265317274195597248077934451075855527')
mpf('7.21658597929406951556806247230383254685067097032105786583650636819627678717747461433940963299310318715204551609940031954265317274195597248077934451075855527')

Limit m

At large m it becomes difficult to directly optimize m numerically, so another approach is desirable. A Taylor approximation of the sinusoid about its peak, where it most differs from a linear function, is a quadratic polynomial. This can be used to analyze the effects of quantization in the limit m A. The difference between the MS quantization error of a sinusoid with an amplitude A and the MS quantization error 1/12 of a linear function is proportional to (Fig. 4):

(7)MS112f(a)=04a+2/2((x2a)2112)dx+k=14a+4k2/24a+4k+2/2((x2ak)2112)dx=160(4a+216a24a1+k=1(4a+4k+2(16a2+4a(8k1)+16k24k1)4a+4k2(16a2+4a(8k+1)+16k2+4k1))),

when the amplitude A is an integer plus a real number 0.5<a0.5. The sum in Eq. 7 appears to converge, whereas leaving out the term 112 would result in the sequence of partial sums growing without bound, indicating that no matter which value of a is chosen, (MS112)/MS0 and MS112 as m.

enter image description here
Figure 4. f(a) and f(a) of Eq. 7. The shape of f(a) looks identical to the shape of RRMSE for large m in Fig. 1.

By symbolically differentiating f(a) defined in Eq. 7 with respect to a (Fig. 4) and by finding the zero of f(a) near a=0.157, the optimal a at m can be computed to quite a bit of precision, in Python (continued):

def f(a):
    a = mp.mpf(a)
    return (mp.sqrt(4*a + 2)*(16*a**2 - 4*a - 1) + mp.nsum(lambda k: (mp.sqrt(4*a + 4*k + 2)*(16*a**2 + 4*a*(8*k - 1) + 16*k**2 - 4*k - 1) - mp.sqrt(4*a + 4*k - 2)*(16*a**2 + 4*a*(8*k + 1) + 16*k**2 + 4*k - 1)), [1, mp.inf]))/60

def Df(a):  # Derivative of f(a)
    a = mp.mpf(a)
    return mp.sqrt(2)*(16*a**2 + 4*a - 1)/(12*mp.sqrt(2*a + 1)) + mp.nsum(lambda k: (mp.sqrt(4*a + 4*k - 2)*(16*a**2 + 4*a*(8*k + 1) + 16*k**2 + 4*k - 1) - mp.sqrt(4*a + 4*k + 2)*(16*a**2 + 4*a*(8*k - 1) + 16*k**2 - 4*k - 1))/(12*mp.sqrt(2*a + 2*k + 1)*mp.sqrt(2*a + 2*k - 1)), [1, mp.inf])    

to_max_digits(lambda: mp.findroot(lambda a: Df(a), 0.157), 63, 83, double_digits)

which gives a0.156936321399. This can be used to create an approximation of the optimal A as function of m, intended for large m20:

(8)A2m11+0.156936321399+e1.27498190170.3464088917m,

where the coefficients in the exponent were calculated by a linear fit at m{21,22} to a linearization of optimal A values of Table 1 or equivalently Table 2. The error from using the approximation is shown in Fig. 5.

enter image description here
Figure 5: Absolute error in the approximation of optimal A by Eq. 8 as function of m. For m{21,22}, which were used for fitting, and for m{23,24}, the absolute approximation error was less than 108.

Out of curiosity, I also computed the worst-case a that gives the largest MS quantization error as m, by finding the zero of f(a) near a=0.43, which turned out to be at a0.433510875868.

Conclusion

The two definitions of optimality appear to be equivalent, to convincing numerical precision. As m, the optimal value of A approaches approximately 2m11+0.156936321399 (or more accurately for large finite m the approximation of Eq. 8) and the quantization error reduction (by def. 1 SNR or def. 2 THD) in dB from choosing the optimal value approaches zero, compared to choosing another large value such as A=2m11 or the nearly worst-case choice A=2m10.5.

At the optimal amplitude A, the least squares (LS) sinusoid is of the same frequency and phase as the sinusoid being quantized, but has a somewhat lower amplitude a1 given in Table 2. This is somewhat counterintuitive. To minimize THD (or to maximize SNR with the sinusoid being approximated as the signal) of approximating a sinusoid of amplitude a1 using a waveform of m-bit numbers with values in range 2m12m11 that is constructed by quantizing (by rounding to the nearest integer) a sinusoid of amplitude A, one must choose optimal a1 and A that are not equal.

The results are applicable to continuous time without sampling, or to sampling in the limit ffs, where f is the sinusoid frequency and fs is the sampling frequency. In general, optimality is not preserved by sampling. Random sampling with random times of the samples will preserve definition 1 SNR optimality, if the distribution of the sinusoid phase (modulo 2π) at the samples is uniform. Also, for irrational f/fs, the same optimality is preserved for the same reason, see equidistribution theorem. Definition 1 SNR optimality vanishes with rational f/fs, because the distribution of sinusoid phases will not be uniform.


The phase does matter, a lot, according to my numerical results in the other question. It's not a WLOG t get rid of it, by ignoring it you are study an extremely small subset of a general solution.
Cedron Dawg

@CedronDawg there is no sampling, so the phase does not matter. For a non-zero phase shift of the cosine, both the sinusoid and its quantization would be shifted identically in time, and therefore the quantization noise would also be shifted in time identically and have identical power (mean square) and power spectrum compared to the zero phase shift case.
Olli Niemitalo

In other words, in continuous time, quantization is a waveshaper and a waveshaper is a time-invariant system, and a phase shift of a sinusoid is equivalent to a time shift. A time shift does not change the power spectrum.
Olli Niemitalo

"It is enough to do the analysis in the first quarter-period of the cosine": I don't think this is safe assumption since an even numbered grid that's centered on zero is always asymmetric. For 16-bit it goes from -32768 to +32767. Since the probability density function of the sine wave is maximum in this range and you are looking at very small differences, this will probably make a non trivial difference. In other words: your optimum amplitude will different for a positive half wave then a negative one.
Hilmar

@Hilmar the question states that a sinusoid is quantized. A sinusoid is antiperiodic. The question states that quantization is done by rounding to the nearest integer. For example for m=16, amplitudes of the sinusoid that result in rounding of parts of the sinusoid to -32768 are prohibited in the question, because the rounding would also produce 32768 (at the opposite phase) which is not a 16-bit number.
Olli Niemitalo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.