কোয়ান্টাইজেশন ও কোয়ান্টাইজেশন এরর
এই পাঠে যা শিখবেন
- কোয়ান্টাইজেশনের সংজ্ঞা এবং কেন এটি স্যাম্পলিং থেকে ভিন্ন একটি প্রক্রিয়া
- একটি ইউনিফর্ম কোয়ান্টাইজার হাতে বাস্তবায়ন করা (মিড-ট্রেড, uniform step)
- প্রতিটি স্যাম্পলের প্রকৃত কোয়ান্টাইজেশন এরর সত্যিকারের কোড দিয়ে গণনা করা
- কোয়ান্টাইজেশন নয়েজ পাওয়ার থেকে SNR হিসেব করা, ও বিট-সংখ্যার সাথে এর সম্পর্ক বোঝা
১ · কোয়ান্টাইজেশন কী
L05-L06-এ আমরা দেখেছি স্যাম্পলিং একটি সিগন্যালকে সময়ে ডিসক্রিট করে — নির্দিষ্ট মুহূর্তে মান নেওয়া হয়। কিন্তু সেই মানগুলো এখনও ধারাবাহিক (যেকোনো রিয়েল সংখ্যা হতে পারে)। একটি ডিজিটাল সিস্টেম (কম্পিউটার, মাইক্রোকন্ট্রোলার) সসীম সংখ্যক বিট দিয়ে সংখ্যা সংরক্ষণ করে, তাই প্রতিটি অ্যামপ্লিটিউড মানকেও একটি সসীম সংখ্যক ডিসক্রিট লেভেলের একটিতে গোল করতে হয় — একেই বলে কোয়ান্টাইজেশনQuantizationএকটি ধারাবাহিক অ্যামপ্লিটিউড মানকে একটি সসীম সংখ্যক ডিসক্রিট লেভেলের নিকটতমটিতে গোল করার প্রক্রিয়া।। স্যাম্পলিং সময়-অক্ষে ডিসক্রিটাইজেশন, কোয়ান্টাইজেশন অ্যামপ্লিটিউড-অক্ষে ডিসক্রিটাইজেশন — দুটো মিলেই একটি সম্পূর্ণ ADC পাইপলাইন তৈরি করে (L08-এ একত্রিত হবে)।
$b$ বিট দিয়ে $2^b$টি ডিসক্রিট লেভেল প্রকাশ করা যায় — ৩ বিট = ৮ লেভেল, ৪ বিট = ১৬ লেভেল, ১৬ বিট (CD অডিও) = ৬৫,৫৩৬ লেভেল।
রেঞ্জ $[x_{min}, x_{max}]$-কে $2^b$ ভাগে ভাগ করলে স্টেপ সাইজ $\Delta = (x_{max}-x_{min})/2^b$ — যত বড় $\Delta$, তত মোটা গোলযোগ।
২ · একটি হাতে-লেখা কোয়ান্টাইজার ও প্রকৃত এরর
নিচের কোড সেলে একটি মিড-ট্রেড ইউনিফর্ম কোয়ান্টাইজার হাতে লেখা হয়েছে — এটি একটি মানকে $2^{bits}$টি সমান-দৈর্ঘ্যের ভাগে ভাগ করে প্রতিটি ভাগের মাঝামাঝি মান রিটার্ন করে। একটি ৫ Hz সাইন সিগন্যাল ($f_s=64$ Hz, $N=16$ স্যাম্পল) ৩-বিট (৮ লেভেল) দিয়ে কোয়ান্টাইজ করে প্রতিটি স্যাম্পলের এরর ($x[n]-x_q[n]$) এবং শেষে সিগন্যাল/নয়েজ পাওয়ার থেকে SNR গণনা করা হচ্ছে।
import math
def quantize(x, bits, xmin=-1.0, xmax=1.0):
"""মিড-ট্রেড ইউনিফর্ম কোয়ান্টাইজার -- [xmin, xmax] রেঞ্জকে 2**bits ভাগে ভাগ করে"""
levels = 2 ** bits
step = (xmax - xmin) / levels
idx = int((x - xmin) / step)
idx = max(0, min(levels - 1, idx)) # রেঞ্জের বাইরে গেলে ক্ল্যাম্প করা
xq = xmin + (idx + 0.5) * step # সেই ভাগের মাঝামাঝি মান
return xq, step, levels
fs = 64.0
f = 5.0
N = 16
bits = 3
samples = [math.sin(2 * math.pi * f * n / fs) for n in range(N)]
print(f"{'n':>3} | {'x[n]':>9} | {'xq[n]':>9} | {'error':>9}")
errors = []
for n, x in enumerate(samples):
xq, step, levels = quantize(x, bits)
e = x - xq
errors.append(e)
print(f"{n:>3} | {x:>9.5f} | {xq:>9.5f} | {e:>9.5f}")
print(f"\nবিটস={bits}, লেভেল={levels}, স্টেপ সাইজ={step}")
signal_power = sum(x * x for x in samples) / N
noise_power = sum(e * e for e in errors) / N
snr = 10 * math.log10(signal_power / noise_power)
print(f"signal power = {signal_power:.6f}")
print(f"noise power = {noise_power:.8f}")
print(f"SNR = {snr:.3f} dB")
৩ · বিট বাড়ালে কী হয়
একই সিগন্যালকে ৩ বিটের বদলে ৪ বিট (১৬ লেভেল) দিয়ে কোয়ান্টাইজ করলে স্টেপ সাইজ অর্ধেক ($0.25 \to 0.125$) হয়ে যায়, নয়েজ পাওয়ার কমে ($0.00603 \to 0.00149$), আর SNR বাড়ে ($18.904 \to \mathbf{24.967}$ dB) — এই সম্পর্ক নিচের অনুশীলনে নিজে যাচাই করুন।
কোয়ান্টাইজেশন এরর কোনো "বাগ" নয় — এটি সসীম বিটে অসীম-নির্ভুল সংখ্যা সংরক্ষণের একটি অপরিহার্য, গাণিতিকভাবে নিয়ন্ত্রিত পরিণতি। বিট-সংখ্যা বাড়ালে এরর কমে, ব্যয় (মেমরি, ব্যান্ডউইথ) বাড়ে — এটাই ADC ডিজাইনের একটি মূল ট্রেড-অফ, যা L08-এ সম্পূর্ণ ADC/DAC পাইপলাইনে প্রয়োগ হবে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ কোয়ান্টাইজেশন এরর কি সবসময় ধনাত্মক নাকি ঋণাত্মক হবে? উপরের টেবিল দেখে বলুন।
দুটোই — টেবিলে $n=0$-এ এরর $-0.125$ (ঋণাত্মক, কোয়ান্টাইজড মান আসলের চেয়ে বেশি), আবার $n=3$-এ এরর $+0.12018$ (ধনাত্মক, কোয়ান্টাইজড মান আসলের চেয়ে কম)। মিড-ট্রেড কোয়ান্টাইজার সবসময় নিকটতম লেভেলে গোল করে, তাই এরর সবসময় $[-\Delta/2, +\Delta/2]$ রেঞ্জে থাকে — গড়ে প্রায় শূন্যের কাছাকাছি, কিন্তু প্রতিটি পৃথক স্যাম্পলে যেকোনো চিহ্ন হতে পারে।
প্র ০২
যদি সিগন্যালের রেঞ্জ $[-1,1]$-এর বাইরে চলে যায় (যেমন একটি স্যাম্পল $1.5$), তাহলে উপরের
quantize() ফাংশন কী করবে?
কোডে idx = max(0, min(levels - 1, idx)) লাইনটি ইনডেক্সকে ক্ল্যাম্প (clamp) করে —
অর্থাৎ $1.5$ সর্বোচ্চ লেভেলেই আটকে যাবে, আসল মান $1.5$ হলেও কোয়ান্টাইজড আউটপুট রেঞ্জের শীর্ষ লেভেলের
মাঝামাঝি মানই দেবে। এটাকে বলে ক্লিপিং — রেঞ্জের বাইরের মানে কোয়ান্টাইজেশন এরর হঠাৎ
অনেক বড় হয়ে যায়, তাই বাস্তব ADC ডিজাইনে ইনপুট রেঞ্জ ঠিকভাবে সেট করা (gain staging) গুরুত্বপূর্ণ।
প্র ০৩
SNR হিসাবের সূত্র 10*log10(signal_power/noise_power) কেন ১০ দিয়ে গুণ করা হয়, ২০ দিয়ে
নয় (যেমন কখনো কখনো amplitude-ratio-তে দেখা যায়)?
signal_power ও noise_power ইতিমধ্যে "পাওয়ার" রাশি (অ্যামপ্লিটিউডের বর্গের
গড়), আর ডেসিবেল সংজ্ঞা অনুযায়ী পাওয়ার-অনুপাতের জন্য $10\log_{10}$ ব্যবহার হয় ($20\log_{10}$
ব্যবহার হয় যখন সরাসরি অ্যামপ্লিটিউড-অনুপাত নেওয়া হয়, কারণ পাওয়ার $\propto$ অ্যামপ্লিটিউড², আর
$10\log_{10}(A^2)=20\log_{10}(A)$)। উপরের কোডে যেহেতু আমরা সরাসরি পাওয়ার (বর্গের গড়) নিয়েছি, $10$
দিয়ে গুণ করাই সঠিক — এই কনভেনশন M11-এর SNR পাঠগুলোতেও (L49) একইভাবে ব্যবহৃত হবে।
অনুশীলন
-
চিন্তা করুন: উপরের কোড সেলে
bits = 3-কেbits = 4-এ বদলালে লেভেল-সংখ্যা ও স্টেপ সাইজ কত হবে? SNR বাড়বে না কমবে বলে আপনার ধারণা?লেভেল $2^4=16$ (৩-বিটের ৮ থেকে দ্বিগুণ), স্টেপ সাইজ $\Delta=2/16=0.125$ (আগের অর্ধেক)। স্টেপ সাইজ অর্ধেক মানে গড় এরর ম্যাগনিটিউডও কমবে, তাই নয়েজ পাওয়ার কমবে এবং SNR বাড়বে।
-
পরীক্ষা করুন: কোড সেলে
bits = 3-কেbits = 4-এ পরিবর্তন করে Run চেপে দেখুন প্রকৃত SNR কত হয়।রান করলে
levels=16,step=0.125,noise power ≈ 0.00149364, এবং SNR ≈ 24.967 dB দেখাবে — ৩-বিটের ১৮.৯০৪ dB থেকে প্রায় ৬ dB বেড়েছে, যা "প্রতি বিটে প্রায় ৬ dB SNR বৃদ্ধি" নিয়মের ($6.02$ dB/বিট) সাথে সামঞ্জস্যপূর্ণ।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পরবর্তী পাঠ — ADC ও DAC কনভার্সন L08 এই পাঠের কোয়ান্টাইজার পুনরায় ব্যবহার করে সম্পূর্ণ sample+quantize পাইপলাইন এবং DAC-এর reconstruction ধাপ দেখানো হবে।
- পূর্ববর্তী পাঠ — অ্যালিয়াসিং L06 স্যাম্পলিং-এর ফ্রিকোয়েন্সি-ডোমেইন সমস্যা — এই পাঠের কোয়ান্টাইজেশন-এর অ্যামপ্লিটিউড-ডোমেইন সমস্যার প্রতিরূপ।
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ স্যাম্পলিং, কনভোলিউশন, Z-ট্রান্সফর্ম, DTFT/DFT, FFT, FIR/IIR ফিল্টার ডিজাইন, মাল্টিরেট প্রসেসিং, স্পেকট্রাল এস্টিমেশন, র্যান্ডম সিগন্যাল প্রসেসিং, বাস্তব প্রয়োগ ও ক্যাপস্টোন।