পাঠ ৩৪ · ৫৭-এর মধ্যে · মডিউল ৭
Home / Courses / Digital Signal Processing / FIR ফিল্টার ডিজাইন

FIR ফিল্টার ডিজাইন ট্রেড-অফ — অর্ডার বনাম পারফরম্যান্স

FIR filter design trade-offs — order vs performance
১১ মিনিট পড়া উচ্চ · Advanced Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • ফিল্টার অর্ডার (ট্যাপ সংখ্যা) বাড়ালে/কমালে ঠিক কী কী পরিবর্তন হয় — একটি সত্যিকারের পাশাপাশি তুলনা
  • প্যাসব্যান্ড ফ্ল্যাটনেস, স্টপব্যান্ড এটেনুয়েশন, ও ট্রানজিশন-ব্যান্ড প্রস্থের মধ্যে সম্পর্ক
  • কেন এই উন্নতি "বিনামূল্যে" নয় — কম্পিউটেশন কস্টের সাথে সরাসরি সম্পর্ক (L33-এর O(M) থেকে সংযুক্ত)
  • বাস্তব ডিজাইন সিদ্ধান্তে কীভাবে এই ট্রেড-অফ বিবেচনা করতে হয়

১ · ট্যাপ সংখ্যা কেন গুরুত্বপূর্ণ

L31-এ আমরা M=31 ট্যাপের একটি ফিল্টার ডিজাইন করেছিলাম এবং দেখেছিলাম এটি ৬০ Hz উপাদান −৪১.২৭ dB দমন করে, ১০ Hz প্রায় অক্ষত রেখে। কিন্তু M-এর মান কীভাবে বেছে নেওয়া হয়েছিল? এই পাঠে আমরা সরাসরি দেখব — একই কাটঅফ ফ্রিকোয়েন্সিতে, ভিন্ন M বেছে নিলে ফলাফল কীভাবে বদলায়। উইন্ডোড-সিংক পদ্ধতিতে (L31), ফিল্টারের দৈর্ঘ্য সরাসরি নিয়ন্ত্রণ করে সিংক ফাংশনের কতটুকু অংশ রাখা হচ্ছে — বেশি ট্যাপ মানে সিংকের আরও বেশি "লব" (lobe) রাখা, যা তাত্ত্বিকভাবে আদর্শ ব্রিক-ওয়াল রেসপন্সের আরও কাছাকাছি নিয়ে যায়।

২ · কোড দিয়ে পাশাপাশি তুলনা

নিচে একই ডিজাইন ফাংশন দিয়ে দুটি ফিল্টার তৈরি করা হয়েছে — একটি ছোট (M=11) ও একটি বড় (M=41) — উভয়ই fs=200 Hz-এ fc=30 Hz কাটঅফের লো-পাস, এবং L31-এর একই ১০ Hz + ৬০ Hz টেস্ট সিগন্যালে প্রয়োগ করা হয়েছে (গ্রুপ ডিলে ট্রিম করে, L31-এর পদ্ধতিতে)।

Python
import math

fs = 200.0
f_lo = 10.0
f_hi = 60.0
N = 60
x = [math.sin(2*math.pi*f_lo*n/fs) + math.sin(2*math.pi*f_hi*n/fs) for n in range(N)]

fc = 30.0
fc_norm = fc/fs

def sinc_lp(d, fc_norm):
    if d == 0:
        return 2*fc_norm
    return math.sin(2*math.pi*fc_norm*d)/(math.pi*d)

def design_filter(M):
    center = (M-1)//2
    h_ideal = [sinc_lp(n-center, fc_norm) for n in range(M)]
    w = [0.54 - 0.46*math.cos(2*math.pi*n/(M-1)) for n in range(M)]
    return [h_ideal[n]*w[n] for n in range(M)], center

def convolve(a, b):
    ny = len(a)+len(b)-1
    y = [0.0]*ny
    for n in range(ny):
        s = 0.0
        for k in range(len(b)):
            if 0 <= n-k < len(a):
                s += b[k]*a[n-k]
        y[n] = s
    return y

def dft_mag_at(sig, f, fs):
    Ns = len(sig)
    total = sum(sig[n]*complex(math.cos(-2*math.pi*f*n/fs), math.sin(-2*math.pi*f*n/fs)) for n in range(Ns))
    return abs(total)/Ns

mag_in_lo = dft_mag_at(x, f_lo, fs)
mag_in_hi = dft_mag_at(x, f_hi, fs)

results = {}
for M in [11, 41]:
    h, center = design_filter(M)
    y_full = convolve(x, h)
    y = y_full[center:center+N]
    mag_out_lo = dft_mag_at(y, f_lo, fs)
    mag_out_hi = dft_mag_at(y, f_hi, fs)
    atten_lo = 20*math.log10(mag_out_lo/mag_in_lo)
    atten_hi = 20*math.log10(mag_out_hi/mag_in_hi)
    results[M] = h
    print(f"M={M:>3} taps | প্যাসব্যান্ড (10Hz) এটেনুয়েশন: {atten_lo:>7.4f} dB | স্টপব্যান্ড (60Hz) এটেনুয়েশন: {atten_hi:>7.2f} dB")

print()
print("ট্রানজিশন শার্পনেস -- |H(f)| সরাসরি ফিল্টারের উপর মূল্যায়ন করা (কোনো ইনপুট সিগন্যাল ছাড়াই):")

def freq_response(h, f_norm):
    Nh = len(h)
    return sum(h[n]*complex(math.cos(-2*math.pi*f_norm*n), math.sin(-2*math.pi*f_norm*n)) for n in range(Nh))

print(f"{'f (Hz)':>7} | {'M=11':>10} | {'M=41':>10}")
for f_probe in [25, 30, 32, 35, 40, 45]:
    row = [abs(freq_response(results[M], f_probe/fs)) for M in [11, 41]]
    print(f"{f_probe:>7} | {row[0]:>10.6f} | {row[1]:>10.6f}")

    
প্রকৃত আউটপুট দুই দিক থেকেই M=41-এর সুবিধা দেখায়। প্রথম টেবিলে — M=11-এ প্যাসব্যান্ড এটেনুয়েশন −০.৬৬৩১ dB (কিছুটা রিপল আছে), M=41-এ মাত্র −০.০০৯৮ dB (প্রায় সমতল); আর স্টপব্যান্ডে M=11-এর −৩২.৭৪ dB-এর তুলনায় M=41 পৌঁছায় −৪০.৪১ dB-এ, অর্থাৎ প্রায় ৮ dB বেশি গভীর দমন। দ্বিতীয় টেবিলে ট্রানজিশন অঞ্চলের আকৃতি স্পষ্ট — কাটঅফের ঠিক নিচে f=25 Hz-এ M=41-এর ম্যাগনিটিউড এখনও 0.9226 (প্রায় সম্পূর্ণ পাস), কিন্তু M=11-এর মাত্র 0.6366 (ইতিমধ্যে কমতে শুরু করেছে); আর কাটঅফের ঠিক উপরে f=40 Hz-এ M=41 প্রায় শূন্য (0.0023), অথচ M=11 তখনও উল্লেখযোগ্য (0.2420)। অর্থাৎ M=41-এর ট্রানজিশন অঞ্চল M=11-এর চেয়ে অনেক সংকীর্ণ ও তীক্ষ্ণ — একটি সত্যিকারের, সরাসরি কম্পিউটেড প্রমাণ।

৩ · বিনামূল্যে নয় — কম্পিউটেশন কস্টের দিকটা

L33-এ দেখা হয়েছিল একটি M-ট্যাপ FIR ফিল্টার প্রতিটি আউটপুট নমুনায় প্রায় Mটি গুণ-যোগ করে। তাই M=11 থেকে M=41-এ যাওয়া মানে প্রতি নমুনায় গণনা প্রায় ৪ গুণ বেশি — একটি রিয়েল-টাইম সিস্টেমে (যেমন একটি এমবেডেড অডিও ডিভাইস) এটি ব্যাটারি খরচ, ল্যাটেন্সি, বা প্রসেসর লোডের উপর সরাসরি প্রভাব ফেলতে পারে। তাছাড়া বেশি ট্যাপ মানে বেশি গ্রুপ ডিলে ((M-1)/2 নমুনা) — M=41-এ ২০ নমুনার ডিলে, M=11-এ মাত্র ৫ নমুনা — যা লাইভ অডিও/কমিউনিকেশন সিস্টেমে শ্রবণযোগ্য/অনুভবযোগ্য বিলম্ব তৈরি করতে পারে।

বেশি ট্যাপ (M বড়)
শার্প ট্রানজিশন, গভীর স্টপব্যান্ড এটেনুয়েশন, সমতল প্যাসব্যান্ড — কিন্তু বেশি গণনা ও বেশি গ্রুপ ডিলে।
কম ট্যাপ (M ছোট)
দ্রুত গণনা, কম ডিলে, কম মেমোরি — কিন্তু চওড়া ট্রানজিশন, কম গভীর এটেনুয়েশন, বেশি প্যাসব্যান্ড রিপল।
মূল কথা · Key takeaway

FIR ফিল্টার ডিজাইনে "সেরা" ফিল্টার বলে কিছু নেই — শুধু প্রয়োগের চাহিদার সাথে মেলানো একটি ভারসাম্য আছে। একটি স্লো, উচ্চ-নির্ভুলতার অফলাইন বিশ্লেষণে M=৫০০+ ট্যাপ ব্যবহার করা সহজেই যুক্তিসঙ্গত হতে পারে, কিন্তু একটি ব্যাটারি-চালিত রিয়েল-টাইম ডিভাইসে M=১০-২০ ট্যাপের বেশি না যাওয়াই বুদ্ধিমানের কাজ হতে পারে। এই ট্রেড-অফ M8-এ (L35 থেকে) IIR ফিল্টারের সাথে তুলনার সময়ও ফিরে আসবে — IIR প্রায়ই একই শার্পনেস অনেক কম কোয়েফিসিয়েন্টে অর্জন করতে পারে, কিন্তু লিনিয়ার ফেজ ও নিঃশর্ত স্ট্যাবিলিটির সুবিধা হারিয়ে।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ কোড সেলের ফলাফলে M=41-এর প্যাসব্যান্ড এটেনুয়েশন (−০.০০৯৮ dB) M=11-এর (−০.৬৬৩১ dB) চেয়ে অনেক ভালো কেন — সরাসরি সিংক-উইন্ডো তত্ত্ব দিয়ে ব্যাখ্যা করুন।

M=41-এর ফিল্টার সিংক ফাংশনের অনেক বেশি "লব" ধরে রাখে (২০টি করে দুই পাশে, বনাম M=11-এ মাত্র ৫টি) — তাই এটি আদর্শ (ideal), অসীম-দৈর্ঘ্যের সিংক ফাংশনের অনেক কাছাকাছি একটি approximation। উইন্ডো ফাংশনের প্রান্তে হওয়া "কাটা"-জনিত ত্রুটি (L24-এর স্পেকট্রাল লিকেজের সাথে সম্পর্কিত) M=41-এ আনুপাতিকভাবে অনেক কম, তাই প্যাসব্যান্ডে রিপল কম, রেসপন্স আরও সমতল।

প্র ০২ যদি M আরও বাড়িয়ে ১০১ ট্যাপ করা হয়, তাহলে স্টপব্যান্ড এটেনুয়েশন কি সীমাহীনভাবে বাড়তেই থাকবে?

ট্রানজিশন-ব্যান্ডের শার্পনেস ও কিছুটা এটেনুয়েশনের গভীরতা M বাড়ানোর সাথে উন্নত হতে থাকবে, কিন্তু একটি নির্দিষ্ট উইন্ডো ফাংশনের (এখানে হ্যামিং) নিজস্ব একটি "সর্বোচ্চ সম্ভাব্য স্টপব্যান্ড এটেনুয়েশন" সীমা আছে — এটি মূলত উইন্ডোর সাইড-লোবের আকৃতির উপর নির্ভর করে, M-এর উপর নয় (এটি একটি সুপরিচিত, স্ট্যান্ডার্ড উইন্ডো-ডিজাইন তত্ত্ব)। হ্যামিং উইন্ডোর জন্য এই সীমা প্রায় −৫৩ dB-এর কাছাকাছি — এর বেশি এটেনুয়েশন চাইলে M বাড়ানো নয়, বরং ভিন্ন একটি উইন্ডো ফাংশন (যেমন ব্ল্যাকম্যান) দরকার হয়।

প্র ০৩ একটি ব্যাটারি-চালিত হিয়ারিং-এইড ডিভাইসের জন্য ফিল্টার ডিজাইন করতে হলে, M=১১ আর M=৪১-এর মধ্যে কোনটি বেছে নেবেন এবং কেন?

সম্ভবত M=১১-এর কাছাকাছি একটি ছোট ফিল্টার — একটি হিয়ারিং-এইডে কম ব্যাটারি খরচ ও কম শ্রবণযোগ্য বিলম্ব (ব্যবহারকারী নিজের কথা আর ফিল্টার-করা আউটপুটের মধ্যে বিলম্ব অনুভব করলে অস্বস্তিকর হয়) সাধারণত এটেনুয়েশনের সামান্য ক্ষতির চেয়ে বেশি গুরুত্বপূর্ণ। এটাই ঠিক এই পাঠের মূল বার্তা — সঠিক পছন্দ সবসময় প্রয়োগের সুনির্দিষ্ট চাহিদার উপর নির্ভর করে, কোনো সার্বজনীন "সঠিক উত্তর" নেই।

অনুশীলন

  1. চিন্তা করুন: কোড সেলে for M in [11, 41]:-এ একটি তৃতীয় মান 21 যোগ করলে ([11, 21, 41]), M=21-এর প্যাসব্যান্ড ও স্টপব্যান্ড এটেনুয়েশন M=11 আর M=41-এর মধ্যে কোথায় পড়বে বলে আপনার ধারণা?

    M=21-এর ফলাফল আনুমানিকভাবে M=11 আর M=41-এর মাঝামাঝি হবে — প্যাসব্যান্ড এটেনুয়েশন −০.৬৬ আর −০.০১ dB-এর মধ্যে কোথাও, স্টপব্যান্ড এটেনুয়েশন −৩২.৭ আর −৪০.৪ dB-এর মধ্যে কোথাও। ট্যাপ সংখ্যা বাড়ার সাথে উন্নতি একঘেয়েভাবে (monotonically) হয়, লাফিয়ে নয়।

  2. পরীক্ষা করুন: কোড সেলে for M in [11, 41]:-কে for M in [11, 21, 41]:-এ পরিবর্তন করে Run চেপে আপনার হিসেব যাচাই করুন।

    রান করলে M=21-এর সারি M=11 আর M=41-এর মাঝামাঝি একটি মান দেখাবে (উভয় এটেনুয়েশনেই) — নিশ্চিত করে যে ফিল্টার কর্মক্ষমতা ট্যাপ সংখ্যার সাথে ক্রমাগত (smoothly), লাফিয়ে নয়, উন্নত হয়। মনে রাখবেন দ্বিতীয় টেবিলের results ডিকশনারিতেও M=21 যোগ করতে চাইলে ট্রানজিশন-শার্পনেস লুপেও [11, 41]-কে [11, 21, 41]-এ বদলাতে হবে।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
FIR ফিল্টার ইমপ্লিমেন্টেশন — ডাইরেক্ট ফর্ম