সফ্টওয়্যারটিতে কীভাবে একটি এএফএসকে সিগন্যালটি তৈরি করা যায়


14

আমি একটি অডিও চ্যানেল (স্পিকার / মাইক) এর মাধ্যমে বাইনারি ডেটা এক ডিভাইস থেকে অন্য ডিভাইসে স্থানান্তরিত করার চেষ্টা করছি। আমি প্যাকেট রেডিও হিসেবে AFSK (অডিও ফ্রিকোয়েন্সি শিফট keying) ব্যবহার, সঙ্গে এবং দুই ফ্রিকোয়েন্সি এবং । আমি রুবিতে কিছুটা খেলেছি এবং আমার প্রথম প্রয়োগটি এখন পর্যন্ত খুব ভালভাবে কাজ করে এমন একটি ক্লাসিক ইনসিহরেন্ট ডেমোডুলেটরকে অনুকরণ করে।1200 বডমিএকটিR=1200 Hz হয়গুলিপিএকটি=2200 Hz হয়

সমস্যাটি হ'ল, আমি এটি এমন একটি মোবাইল প্ল্যাটফর্মে বন্দরের চেষ্টা করছি যেখানে কর্মক্ষমতা একটি উদ্বেগজনক বিষয় এবং আমার বর্তমান সমাধানটি খুব ধীর। সফ্টওয়্যারটিতে এএফএসকে ধ্বংস করার বিভিন্ন উপায় আমি পেয়েছি:

  • স্লাইডিং ডিএফটি (এফএফটি)
  • স্লাইডিং গার্জেল ফিল্টার
  • ফেজ লক লুপ
  • জিরো ক্রসিং

কি উপায় হবে? বেছে নিতে অনেকগুলি বিকল্প রয়েছে। আমি নিশ্চিত যে আরও আরও বিকল্প উপলব্ধ আছে। আমি উপরে বর্ণিত বিষয়গুলির চেয়ে আরও ভাল সমাধানগুলি সম্ভবত রয়েছে? কারও কাছে কি আমার কাছে কোডের উদাহরণ রয়েছে? আমি উদ্বিগ্ন

  • পারফরম্যান্স (মোবাইল প্ল্যাটফর্মে চালানো উচিত, একটি আইওএস বা অ্যান্ড্রয়েড ডিভাইস বলুন)
  • স্থায়িত্ব (কিছু গোলমাল পরিচালনা করতে সক্ষম হওয়া উচিত)

কোনও পরামর্শ এবং ইঙ্গিতগুলি প্রশংসা করা হয়!


3
আমি মনে করি আপনি সম্ভবত যে মোবাইল ডিভাইসগুলি লক্ষ্য করছেন সেগুলির সামর্থ্যগুলি ছোট করে বিক্রি করবেন selling মনে রাখবেন যে আধুনিক ডিভাইসগুলি হ'ল 1 গিগাহার্জ-এর বেশি ঘড়ির গতি সহ মাল্টিকোর প্রসেসর। এফএসকে ডেমোডুলেটারের সাথে <10 কেএসপিএস সংকেত প্রক্রিয়াকরণে কোনও পারফরম্যান্স সমস্যা উপস্থিত করা উচিত নয়। তবে আপনার বিদ্যমান পদ্ধতির (যা আমার কাছে চিহ্ন / স্পেস ফিল্টারিংয়ের মতো মনে হয়) আধুনিক মোবাইল প্ল্যাটফর্মে রিয়েল টাইমে চালাতে সক্ষম না হওয়ার কোনও কারণ নেই। এমনকি আরও পরিশীলিত পিএলএল-ভিত্তিক পদ্ধতির আপনার প্রসেসিং খামে আরামদায়কভাবে ফিট করা উচিত। আমি আপনার বিদ্যমান কোডটি কিছুটা প্রোফাইল করব।
জেসন আর

উত্তর:


9

আমি মনে করি আপনি একটি পর্যায়-লকড লুপের সাথে ডেমোডুলেটর বিট-ত্রুটি হারের (বিইআর) দিক দিয়ে সেরা পারফরম্যান্স পেতে পারেন। যদিও আপনার এটি দ্রুত হওয়া দরকার। আমি মনে করি একটি দ্রুত অ্যালগরিদমের জন্য আপনার সেরা বাজি যা এখনও যথাযথভাবে ভাল সম্পাদন করে তা হ'ল শূন্য ক্রসিং।

সাইড নোটে, আমি আপনাকে পরামর্শ দিতে চাই যে আপনি 2200 হার্জেড 2400 হার্জেডে পরিবর্তন করুন। 1200/2200 হার্জেড স্কিমের একটি নিখুঁত বাস্তবায়ন বিচ্ছিন্নতা অর্জন করবে, যেমন নীচের প্লটে প্রায় দুই তৃতীয়াংশ দেখা গেছে, যেখানে 2200 হার্জেজ 1200 হার্জেজে রূপান্তরিত হয়।

1200 Hz এবং 2200 Hz

আপনি যে ব্যান্ডউইথটি ব্যবহার করছেন তা হ্রাস করতে এবং সংযোগকে বিকৃত করবে এমন সংযোজনগুলি এড়াতে আপনাকে পর্বকে অবিচ্ছিন্ন করতে হবে। এমনকি যদি আপনি ট্রান্সমিটার পর্বকে অবিচ্ছিন্ন করে তোলেন, তবুও, এখনও এই সমস্যাটি থাকবে যে 2200 Hz এর চিহ্নগুলিতে সর্বদা বিভিন্ন পর্যায়ের কারণে শূন্য ক্রসিংয়ের সংখ্যা সর্বদা থাকবে না। সাধারণত তাদের চারটি শূন্য ক্রসিং থাকবে তবে কখনও কখনও তাদের তিনটি হবে। অন্যদিকে 1200 হার্জ প্রতীকটিতে সর্বদা দুটি শূন্য ক্রসিং থাকবে কারণ বাড রেট এফএসকে ফ্রিকোয়েন্সিতে সমানভাবে বিভক্ত হয়।

আপনি 2200 Hz থেকে 2400 Hz এ পরিবর্তন করে উভয় সমস্যার সমাধান করতে পারেন। তারপরে চিহ্নগুলি সর্বদা 0 ডিগ্রিতে শুরু হবে এবং শেষ হবে (এভাবে স্বয়ংক্রিয়ভাবে এগুলি তাদের ধাপে ধ্রুবক করে তোলে) এবং তাদের সর্বদা শূন্য ক্রসিংয়ের সংখ্যা থাকবে - দুই এবং চার।

1200 Hz এবং 2400 Hz


আরে জিম, আপনার বিস্তারিত উত্তরের জন্য ধন্যবাদ! আমার মডিউলেটরটি আসলে সিপিএফএসকে করে, অতএব বিরতি কোনও সমস্যা নয়। আমি ইচ্ছাকৃতভাবে 1200 এবং 2200 Hz বাছাই করেছি কারণ হারমোনিকগুলি 1200 এর গুণকগুলির সাথে ওভারল্যাপ করে না Or বা আমি এখানে ভুল করছি? পিএলএল দুর্দান্ত শোনাচ্ছে তবে সেগুলি কীভাবে বাস্তবায়ন করা যায় সে সম্পর্কে আমার আসলেই কোনও ধারণা নেই। আপনি কি সফ্টওয়্যার পিএলএল সম্পর্কে কোনও ভাল উত্স জানতে পেরেছেন?
প্যাট্রিক অসিটি

@ পেট্রিক নো, আপনি সঠিক যে 1200 এবং 2400 হার্জে ওভারল্যাপিং হারমোনিক্স থাকবে। শূন্য-ক্রসিংয়ের প্রসঙ্গে, যদিও আমি সুরেলা বিষয়টিকে মনে করি না। এবং না, আমি ভয় করি যে আমি পিএলএল সম্পর্কে কোনও ভাল অনলাইন উত্স জানি না।
জিম ক্লে

এটি সঠিক নয়। এএফএসকে 1200 বেল 202 অনুসরণ করে এবং এতে বলা হয়েছে যে টোনগুলি 1200 এবং 2200 হওয়া উচিত The ট্রান্সমিটারের ক্ষেত্রে বিচ্ছিন্নতা কখনই ঘটবে না। ওপেন সোর্স এএফএসকে 1200 মডিউলারগুলি পরীক্ষা করে দেখুন, প্রতিটি টোনটির জন্য একটি পর্যায় বৃদ্ধি ট্র্যাক করে মডিউলেশনটি করা হয়: যদি টোন == কম থাকে তবে শেষ_ফেজ + = পিএইচ_একটি শেষ_ফেজ + = পিএইচএইচ এন্ডিফ; পরের_ নমুনা = পাপ (শেষ_পর্ব);
vz0

5

আমি এএফএসকে (বেল ২০২ স্ট্যান্ডার্ড) খুব ভাল ফলাফল সহ 1200 হার্জেড এবং 2200 হার্জেডের জন্য সম্পর্কিত রিসিভারগুলি ব্যবহার করে একটি ডিকোডার তৈরি করেছি।

পাপকোসাইন্

ফলাফলের প্রশস্ততা সংকেত পর্ব থেকে বেশ স্বতন্ত্র এবং আউটপুট এসএনআর খুব ভাল।


এটি হ'ল আমি এর আগে যা চেষ্টা করেছি এবং আমি "ক্লাসিক ইনগোহেনেন্ট ডেমোডুলেটর" বলেছি। হতে পারে আমার বাস্তবায়ন ভ্রান্ত, কিন্তু আমি আশঙ্কা করছি যে ধীর প্রক্রিয়াকরণের কারণে এটি বাফার ওভারফ্লোতে ভুগছে। যাই হোক ধন্যবাদ!
প্যাট্রিক অসিটি

0

আরটিটিওয়াই 45.45 বাউডের ক্ষেত্রে, আপনার কাছে এমন চিহ্নও থাকবে যা কোনও সংখ্যার নমুনা নয়, সুতরাং আপনাকে এমন একটি ফাংশন প্রয়োজন যা প্রতিটি নমুনা বলা যেতে পারে এবং তার প্রতীকটি শেষ হওয়ার পরে তার প্রত্যাবর্তনের মানটিতে সংকেত দেওয়া উচিত। এবং আপনার একটি পর্যায়ে সঞ্চয়ের প্রয়োজন, যা সাইন ওয়েভের পর্বটি যেখানে চলছে তার চলমান ট্যালি রাখে।

প্রতীক পাঠাতে যার দৈর্ঘ্য নমুনা হারের পূর্ণসংখ্য একক নয়, আপনার এই ক্রিয়াকলাপটি প্রয়োজন ...

int millisecondTimer(double milliseconds, double samplerate, int resettime)
{

    static int fracsample=0;
    static int counter=0;
    static int retvalue=0;
    static int first=1;
    static double oldmilliseconds=1.0;
    static int whole_samples=0;
    static int samerror=32768;
    if(resettime==1)
    {
        samerror=0;
        counter=0;
        retvalue=1;
        first=1;
    }
    if(first==1 || milliseconds !=oldmilliseconds)
    {
        double samplesneeded=1;
        double wholesamples=0;
        samplesneeded=(samplerate) * (milliseconds /1000.0);
        samerror=(modf(samplesneeded, &wholesamples)) * 32768.0;
        whole_samples=wholesamples;
        first=0;
    }

    if(counter<=whole_samples)
    {
        retvalue=2;
        counter++;
    }
    else
    {
        counter-=whole_samples;
        retvalue=1;
        fracsample+=samerror;
        oldmilliseconds=milliseconds;
        if(fracsample>=32768)
        {
            fracsample-=32768;
            counter--;
        }

    }
    return retvalue;
}

এটি ব্যবহার করতে, সাইন ওয়েভের পরবর্তী নমুনা তৈরি করুন এবং এই ফাংশনটিতে কল করুন, তারপরে ফেরতের মান দুটির সমান নয় কিনা তা পরীক্ষা করুন। যদি এটি দুটি সমান না হয়, পরবর্তী প্রতীকটিতে এগিয়ে যান এবং সিদ্ধান্ত নেবেন যে আপনি কোনও স্থানের চিহ্ন পাঠাচ্ছেন কিনা, তবে কোডটির ব্লকের ভিতরে আবার এই ফাংশনটি কল করুন যা কার্যকর হবে যখন আপনি জানতে পেরেছেন যে রিটার্নের মান দুটি সমান নয়।

এবং রকবক্স ফার্মওয়্যার থেকে পর্বের সঞ্চালকটি এখানে রয়েছে প্রশস্ততার পরিবর্তনের অনুমতি দেওয়ার জন্য (পুরো ভলিউমটি 32767, 180 ডিগ্রি ফেজের পূর্ণ পরিমাণের -32768)।

signed short lerpsin(float frequency,signed short amplitude,unsigned long samplerate)
{
    /* 128 sixteen bit sine samples + guard point */
    static unsigned long phase=0;
    unsigned int pos =0;
    unsigned short frac=0;
    static unsigned long step=0;
    static float old_frequency=0;
    signed short diff=0;
    static const signed short sinetab[129] =
    {
        0,   1607,   3211,   4807,   6392,   7961,   9511,  11038,
        12539,  14009,  15446,  16845,  18204,  19519,  20787,  22004,
        23169,  24278,  25329,  26318,  27244,  28105,  28897,  29621,
        30272,  30851,  31356,  31785,  32137,  32412,  32609,  32727,
        32767,  32727,  32609,  32412,  32137,  31785,  31356,  30851,
        30272,  29621,  28897,  28105,  27244,  26318,  25329,  24278,
        23169,  22004,  20787,  19519,  18204,  16845,  15446,  14009,
        12539,  11038,   9511,   7961,   6392,   4807,   3211,   1607,
        0,  -1607,  -3211,  -4807,  -6392,  -7961,  -9511, -11038,
        -12539, -14009, -15446, -16845, -18204, -19519, -20787, -22004,
        -23169, -24278, -25329, -26318, -27244, -28105, -28897, -29621,
        -30272, -30851, -31356, -31785, -32137, -32412, -32609, -32727,
        -32767, -32727, -32609, -32412, -32137, -31785, -31356, -30851,
        -30272, -29621, -28897, -28105, -27244, -26318, -25329, -24278,
        -23169, -22004, -20787, -19519, -18204, -16845, -15446, -14009,
        -12539, -11038, -9511,   -7961,  -6392,  -4807,  -3211,  -1607,
        0,
    };
    if(frequency!=old_frequency)
    {
        step = 0x100000000ull*frequency / samplerate;
    }
    phase+=step;
    pos = phase >> 25;
    frac = (phase & 0x01ffffff) >> 9;
    diff = sinetab[pos + 1] - sinetab[pos];
    old_frequency=frequency;
    return ((-((sinetab[pos] + (frac*diff >> 16)))) * amplitude) >> 15;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.