সতর্কতা: OpenSL ES অবচিত হয়েছে। ডেভেলপারদের ওপেন সোর্স Oboe লাইব্রেরি ব্যবহার করা উচিত যা GitHub এ উপলব্ধ। Oboe হল একটি C++ র্যাপার যা একটি API প্রদান করে যা AAudio-এর সাথে সাদৃশ্যপূর্ণ। AAudio উপলব্ধ থাকলে Oboe AAudio-কে কল করে এবং AAudio উপলব্ধ না হলে OpenSL ES-এ ফিরে আসে৷
এই বিভাগের নোটগুলি OpenSL ES 1.0.1 স্পেসিফিকেশনের পরিপূরক।
অবজেক্ট এবং ইন্টারফেস ইনিশিয়ালাইজেশন
OpenSL ES প্রোগ্রামিং মডেলের দুটি দিক যা নতুন ডেভেলপারদের কাছে অপরিচিত হতে পারে তা হল অবজেক্ট এবং ইন্টারফেসের মধ্যে পার্থক্য এবং প্রারম্ভিক ক্রম।
সংক্ষেপে, একটি OpenSL ES অবজেক্ট জাভা এবং C++ এর মতো প্রোগ্রামিং ভাষাতে অবজেক্ট ধারণার অনুরূপ, একটি OpenSL ES অবজেক্ট শুধুমাত্র এর সংশ্লিষ্ট ইন্টারফেসের মাধ্যমে দৃশ্যমান। এতে সমস্ত অবজেক্টের জন্য প্রাথমিক ইন্টারফেস রয়েছে, যাকে SLObjectItf
বলা হয়। একটি বস্তুর জন্য কোন হ্যান্ডেল নেই, শুধুমাত্র বস্তুর SLObjectItf
ইন্টারফেসের একটি হ্যান্ডেল।
একটি OpenSL ES অবজেক্ট প্রথমে তৈরি করা হয়, যা একটি SLObjectItf
প্রদান করে, তারপর উপলব্ধি করে । এটি প্রথমে একটি অবজেক্ট তৈরি করার সাধারণ প্রোগ্রামিং প্যাটার্নের অনুরূপ (যা মেমরির অভাব বা অবৈধ প্যারামিটার ছাড়া অন্য কোনও ক্ষেত্রে ব্যর্থ হওয়া উচিত নয়), এবং তারপর শুরু করা (যা সম্পদের অভাবের কারণে ব্যর্থ হতে পারে)। উপলব্ধি পদক্ষেপ বাস্তবায়নকে প্রয়োজন হলে অতিরিক্ত সংস্থান বরাদ্দ করার জন্য একটি যৌক্তিক জায়গা দেয়।
একটি বস্তু তৈরি করতে API এর অংশ হিসাবে, একটি অ্যাপ্লিকেশন পছন্দসই ইন্টারফেসের একটি অ্যারে নির্দিষ্ট করে যা এটি পরে অর্জন করার পরিকল্পনা করে। মনে রাখবেন যে এই অ্যারেটি স্বয়ংক্রিয়ভাবে ইন্টারফেসগুলি অর্জন করে না; এটি কেবল তাদের অর্জন করার ভবিষ্যতের অভিপ্রায় নির্দেশ করে। ইন্টারফেসগুলি অন্তর্নিহিত বা স্পষ্ট হিসাবে আলাদা করা হয়। একটি স্পষ্ট ইন্টারফেস অ্যারেতে তালিকাভুক্ত করা আবশ্যক যদি এটি পরে অর্জিত হয়। অবজেক্ট ক্রিয়েট অ্যারেতে একটি অন্তর্নিহিত ইন্টারফেস তালিকাভুক্ত করার প্রয়োজন নেই, তবে সেখানে এটি তালিকাভুক্ত করার কোনও ক্ষতি নেই। OpenSL ES-এর আরও এক ধরনের ইন্টারফেস রয়েছে যাকে ডাইনামিক বলা হয়, যা অবজেক্ট তৈরি অ্যারেতে নির্দিষ্ট করার প্রয়োজন নেই এবং অবজেক্ট তৈরি হওয়ার পরে পরে যোগ করা যেতে পারে। অ্যান্ড্রয়েড বাস্তবায়ন এই জটিলতা এড়াতে একটি সুবিধার বৈশিষ্ট্য প্রদান করে, যা বস্তু তৈরিতে গতিশীল ইন্টারফেসে বর্ণিত হয়েছে।
অবজেক্টটি তৈরি এবং উপলব্ধি করার পরে, অ্যাপ্লিকেশনটিকে প্রাথমিক SLObjectItf
এ GetInterface
ব্যবহার করে প্রয়োজনীয় প্রতিটি বৈশিষ্ট্যের জন্য ইন্টারফেস অর্জন করা উচিত।
অবশেষে, অবজেক্টটি তার ইন্টারফেসের মাধ্যমে ব্যবহারের জন্য উপলব্ধ, যদিও মনে রাখবেন কিছু বস্তুর জন্য আরও সেটআপ প্রয়োজন। বিশেষ করে, সংযোগ ত্রুটি সনাক্ত করার জন্য URI ডেটা উৎস সহ একটি অডিও প্লেয়ারের একটু বেশি প্রস্তুতির প্রয়োজন। বিস্তারিত জানার জন্য অডিও প্লেয়ার প্রিফেচ বিভাগটি দেখুন।
আপনার অ্যাপ্লিকেশন বস্তুর সাথে সম্পন্ন করার পরে, আপনি স্পষ্টভাবে এটি ধ্বংস করা উচিত; নীচের ধ্বংস বিভাগ দেখুন.
অডিও প্লেয়ার প্রিফেচ
URI ডেটা সোর্স সহ একটি অডিও প্লেয়ারের জন্য, Object::Realize
রিসোর্স বরাদ্দ করে কিন্তু ডেটা সোর্সের সাথে সংযোগ করে না ( তৈরি ) বা ডেটা প্রাক-আনয়ন শুরু করে না। প্লেয়ার স্টেট SL_PLAYSTATE_PAUSED
বা SL_PLAYSTATE_PLAYING
তে সেট করা হলে এগুলি ঘটে।
এই ক্রমানুসারে অপেক্ষাকৃত দেরী না হওয়া পর্যন্ত কিছু তথ্য এখনও অজানা থাকতে পারে। বিশেষ করে, প্রাথমিকভাবে Player::GetDuration
SL_TIME_UNKNOWN
ফেরত দেয় এবং MuteSolo::GetChannelCount
হয় চ্যানেল গণনা শূন্য সহ সফলভাবে ফেরত দেয় বা ত্রুটির ফলাফল SL_RESULT_PRECONDITIONS_VIOLATED
। এই APIগুলি পরিচিত হওয়ার পরে সঠিক মানগুলি ফেরত দেয়।
প্রাথমিকভাবে অজানা অন্যান্য বৈশিষ্ট্যগুলির মধ্যে রয়েছে নমুনা হার এবং প্রকৃত মিডিয়া বিষয়বস্তুর ধরন বিষয়বস্তুর শিরোনাম পরীক্ষা করার উপর ভিত্তি করে (অ্যাপ্লিকেশন-নির্দিষ্ট MIME প্রকার এবং ধারক প্রকারের বিপরীতে)। এগুলি প্রস্তুত/প্রিফেচের সময় পরেও নির্ধারিত হয়, কিন্তু সেগুলি পুনরুদ্ধার করার জন্য কোনও API নেই।
প্রিফেচ স্ট্যাটাস ইন্টারফেসটি সনাক্ত করার জন্য উপযোগী যখন সমস্ত তথ্য উপলব্ধ থাকে, অথবা আপনার অ্যাপ্লিকেশন পর্যায়ক্রমে ভোট দিতে পারে। মনে রাখবেন যে কিছু তথ্য, যেমন MP3 স্ট্রিমিং এর সময়কাল, কখনও জানা যাবে না।
প্রিফেচ স্ট্যাটাস ইন্টারফেস ত্রুটি সনাক্ত করার জন্যও কার্যকর। একটি কলব্যাক নিবন্ধন করুন এবং কমপক্ষে SL_PREFETCHEVENT_FILLLEVELCHANGE
এবং SL_PREFETCHEVENT_STATUSCHANGE
ইভেন্টগুলি সক্ষম করুন৷ যদি এই দুটি ইভেন্ট একই সাথে বিতরণ করা হয়, এবং PrefetchStatus::GetFillLevel
একটি শূন্য স্তরের প্রতিবেদন করে এবং PrefetchStatus::GetPrefetchStatus
SL_PREFETCHSTATUS_UNDERFLOW
রিপোর্ট করে, তাহলে এটি ডেটা উৎসে একটি অ-পুনরুদ্ধারযোগ্য ত্রুটি নির্দেশ করে। এতে ডেটা উৎসের সাথে সংযোগ করতে অক্ষমতা অন্তর্ভুক্ত কারণ স্থানীয় ফাইলের নাম বিদ্যমান নেই বা নেটওয়ার্ক URI অবৈধ৷
OpenSL ES-এর পরবর্তী সংস্করণ ডেটা উৎসে ত্রুটিগুলি পরিচালনা করার জন্য আরও স্পষ্ট সমর্থন যোগ করবে বলে আশা করা হচ্ছে। যাইহোক, ভবিষ্যতের বাইনারি সামঞ্জস্যের জন্য, আমরা একটি অ-পুনরুদ্ধারযোগ্য ত্রুটি রিপোর্ট করার জন্য বর্তমান পদ্ধতিকে সমর্থন করা চালিয়ে যেতে চাই।
সংক্ষেপে, একটি প্রস্তাবিত কোড ক্রম হল:
-
Engine::CreateAudioPlayer
-
Object:Realize
-
Object::GetInterface
SL_IID_PREFETCHSTATUS
এর জন্য GetInterface -
PrefetchStatus::SetCallbackEventsMask
-
PrefetchStatus::SetFillUpdatePeriod
-
PrefetchStatus::RegisterCallback
-
Object::GetInterface
SL_IID_PLAY
এর জন্য GetInterface -
Play::SetPlayState
কেSL_PLAYSTATE_PAUSED
, বাSL_PLAYSTATE_PLAYING
এ সেট করুন
দ্রষ্টব্য: প্রস্তুতি এবং প্রিফেচিং এখানে ঘটে; এই সময়ের মধ্যে আপনার কলব্যাক পর্যায়ক্রমিক স্থিতি আপডেটের সাথে কল করা হয়।
ধ্বংস করুন
আপনার অ্যাপ্লিকেশন থেকে প্রস্থান করার সময় সমস্ত বস্তু ধ্বংস করতে ভুলবেন না। বস্তুগুলিকে তাদের সৃষ্টির বিপরীত ক্রমে ধ্বংস করা উচিত, কারণ কোনো নির্ভরশীল বস্তু আছে এমন কোনো বস্তুকে ধ্বংস করা নিরাপদ নয়। উদাহরণস্বরূপ, এই ক্রমে ধ্বংস করুন: অডিও প্লেয়ার এবং রেকর্ডার, আউটপুট মিশ্রণ, এবং তারপর অবশেষে ইঞ্জিন।
OpenSL ES স্বয়ংক্রিয় আবর্জনা সংগ্রহ বা ইন্টারফেসের রেফারেন্স গণনা সমর্থন করে না। আপনি Object::Destroy
কল করার পরে, সংশ্লিষ্ট বস্তু থেকে উদ্ভূত সমস্ত বিদ্যমান ইন্টারফেস অনির্ধারিত হয়ে যায়।
Android OpenSL ES বাস্তবায়ন এই ধরনের ইন্টারফেসের ভুল ব্যবহার সনাক্ত করে না। অবজেক্টটি ধ্বংস হয়ে যাওয়ার পরে এই ধরনের ইন্টারফেস ব্যবহার করা চালিয়ে যাওয়া আপনার অ্যাপ্লিকেশন ক্র্যাশ বা অপ্রত্যাশিত উপায়ে আচরণ করতে পারে।
আমরা সুপারিশ করি যে আপনি স্পষ্টভাবে আপনার অবজেক্ট ধ্বংসের ক্রম অংশ হিসাবে প্রাথমিক অবজেক্ট ইন্টারফেস এবং সমস্ত সম্পর্কিত ইন্টারফেস উভয়ই NULL
তে সেট করুন, যা একটি পুরানো ইন্টারফেস হ্যান্ডেলের দুর্ঘটনাজনিত অপব্যবহার রোধ করে।
স্টেরিও প্যানিং
যখন Volume::EnableStereoPosition
একটি মনো উৎসের স্টেরিও প্যানিং সক্ষম করতে ব্যবহার করা হয়, তখন মোট সাউন্ড পাওয়ার লেভেলে 3-dB হ্রাস পায়। উৎসটি এক চ্যানেল থেকে অন্য চ্যানেলে প্যান করায় মোট শব্দ শক্তির স্তরকে স্থির থাকার অনুমতি দেওয়ার জন্য এটি প্রয়োজন। অতএব, আপনার প্রয়োজন হলে শুধুমাত্র স্টেরিও পজিশনিং সক্ষম করুন। আরও তথ্যের জন্য অডিও প্যানিং সম্পর্কিত উইকিপিডিয়া নিবন্ধটি দেখুন।
কলব্যাক এবং থ্রেড
কলব্যাক হ্যান্ডলারগুলিকে সাধারণত সিঙ্ক্রোনাসভাবে বলা হয় যখন বাস্তবায়ন একটি ইভেন্ট সনাক্ত করে। এই পয়েন্টটি অ্যাপ্লিকেশনের ক্ষেত্রে অ্যাসিঙ্ক্রোনাস, তাই অ্যাপ্লিকেশন এবং কলব্যাক হ্যান্ডলারের মধ্যে ভাগ করা যেকোনো ভেরিয়েবলের অ্যাক্সেস নিয়ন্ত্রণ করতে আপনার একটি নন-ব্লকিং সিঙ্ক্রোনাইজেশন পদ্ধতি ব্যবহার করা উচিত। উদাহরণ কোডে, যেমন বাফার সারিগুলির জন্য, আমরা হয় এই সিঙ্ক্রোনাইজেশনটি বাদ দিয়েছি বা সরলতার স্বার্থে ব্লকিং সিঙ্ক্রোনাইজেশন ব্যবহার করেছি। যাইহোক, সঠিক নন-ব্লকিং সিঙ্ক্রোনাইজেশন যেকোনো প্রোডাকশন কোডের জন্য গুরুত্বপূর্ণ।
কলব্যাক হ্যান্ডলারদের অভ্যন্তরীণ নন-অ্যাপ্লিকেশন থ্রেড থেকে ডাকা হয় যেগুলি Android রানটাইমের সাথে সংযুক্ত নয়, তাই তারা JNI ব্যবহার করার অযোগ্য। যেহেতু এই অভ্যন্তরীণ থ্রেডগুলি OpenSL ES বাস্তবায়নের অখণ্ডতার জন্য গুরুত্বপূর্ণ, তাই একটি কলব্যাক হ্যান্ডলারকেও ব্লক করা বা অতিরিক্ত কাজ করা উচিত নয়।
যদি আপনার কলব্যাক হ্যান্ডলারকে JNI ব্যবহার করতে হয় বা কলব্যাকের সমানুপাতিক নয় এমন কাজ চালাতে হয়, তবে হ্যান্ডলারের পরিবর্তে অন্য থ্রেড প্রক্রিয়া করার জন্য একটি ইভেন্ট পোস্ট করা উচিত। গ্রহণযোগ্য কলব্যাক ওয়ার্কলোডের উদাহরণগুলির মধ্যে রয়েছে পরবর্তী আউটপুট বাফার রেন্ডারিং এবং সারিবদ্ধ করা (একটি অডিওপ্লেয়ারের জন্য), এইমাত্র ভর্তি ইনপুট বাফার প্রক্রিয়াকরণ এবং পরবর্তী খালি বাফার (একটি অডিও রেকর্ডারের জন্য), বা সাধারণ API যেমন বেশিরভাগ গেট ফ্যামিলির মতো। কাজের চাপ সম্পর্কিত নীচের কর্মক্ষমতা বিভাগটি দেখুন।
মনে রাখবেন কথোপকথনটি নিরাপদ: একটি অ্যান্ড্রয়েড অ্যাপ্লিকেশন থ্রেড যা JNI-এ প্রবেশ করেছে তাকে সরাসরি OpenSL ES API-কে কল করার অনুমতি দেওয়া হয়েছে, যেগুলি ব্লক করে। যাইহোক, মূল থ্রেড থেকে কল ব্লক করার সুপারিশ করা হয় না, কারণ এর ফলে অ্যাপ্লিকেশন নট রেসপন্ডিং (ANR) হতে পারে।
যে থ্রেডটি একটি কলব্যাক হ্যান্ডলারকে কল করে সে সম্পর্কে সংকল্পটি মূলত বাস্তবায়নের উপরই রয়ে গেছে। এই নমনীয়তার কারণ হল ভবিষ্যতের অপ্টিমাইজেশনের অনুমতি দেওয়া, বিশেষ করে মাল্টি-কোর ডিভাইসে।
কলব্যাক হ্যান্ডলার যে থ্রেডে চলে তা বিভিন্ন কলে একই পরিচয়ের নিশ্চয়তা দেয় না। অতএব, কল জুড়ে সামঞ্জস্যপূর্ণ হতে pthread_self()
দ্বারা ফেরত দেওয়া pthread_t
বা gettid()
দ্বারা ফেরত দেওয়া pid_t
উপর নির্ভর করবেন না। একই কারণে, কলব্যাক থেকে থ্রেড লোকাল স্টোরেজ (TLS) API যেমন pthread_setspecific()
এবং pthread_getspecific()
ব্যবহার করবেন না।
ইমপ্লিমেন্টেশন গ্যারান্টি দেয় যে একই ধরনের, একই বস্তুর জন্য সমসাময়িক কলব্যাক ঘটবে না। যাইহোক, একই বস্তুর জন্য বিভিন্ন ধরণের সমসাময়িক কলব্যাক বিভিন্ন থ্রেডে সম্ভব।
কর্মক্ষমতা
যেহেতু OpenSL ES একটি নেটিভ C API, নন-রানটাইম অ্যাপ্লিকেশন থ্রেড যেগুলি OpenSL ES-কে কল করে তাদের কোনো রানটাইম-সম্পর্কিত ওভারহেড নেই যেমন আবর্জনা সংগ্রহের বিরতি। নীচে বর্ণিত একটি ব্যতিক্রমের সাথে, এটি ব্যতীত ওপেনএসএল ইএস ব্যবহারে কোনও অতিরিক্ত কর্মক্ষমতা সুবিধা নেই। বিশেষ করে, OpenSL ES-এর ব্যবহার বর্ধিতকরণের গ্যারান্টি দেয় না যেমন কম অডিও লেটেন্সি এবং প্ল্যাটফর্মটি সাধারণত যা প্রদান করে তার চেয়ে উচ্চতর সময়সূচী অগ্রাধিকার। অন্যদিকে, অ্যান্ড্রয়েড প্ল্যাটফর্ম এবং নির্দিষ্ট ডিভাইস বাস্তবায়নের বিকাশ অব্যাহত থাকায়, একটি ওপেনএসএল ইএস অ্যাপ্লিকেশন ভবিষ্যতের সিস্টেম কর্মক্ষমতা উন্নতি থেকে উপকৃত হওয়ার আশা করতে পারে।
এরকম একটি বিবর্তন হল অডিও আউটপুট লেটেন্সি হ্রাসের জন্য সমর্থন। হ্রাসকৃত আউটপুট লেটেন্সির আন্ডারপিনিংগুলি প্রথমে Android 4.1 (API স্তর 16) এ অন্তর্ভুক্ত করা হয়েছিল এবং তারপরে Android 4.2 (API স্তর 17) এ অব্যাহত অগ্রগতি ঘটেছে। android.hardware.audio.low_latency
বৈশিষ্ট্য দাবি করে এমন ডিভাইস বাস্তবায়নের জন্য এই উন্নতিগুলি OpenSL ES এর মাধ্যমে উপলব্ধ। যদি ডিভাইসটি এই বৈশিষ্ট্যটি দাবি না করে তবে Android 2.3 (API স্তর 9) বা তার পরে সমর্থন করে, তাহলে আপনি এখনও OpenSL ES API ব্যবহার করতে পারেন তবে আউটপুট লেটেন্সি বেশি হতে পারে। নিম্ন আউটপুট লেটেন্সি পাথটি শুধুমাত্র তখনই ব্যবহৃত হয় যখন অ্যাপ্লিকেশনটি ডিভাইসের নেটিভ আউটপুট কনফিগারেশনের সাথে সামঞ্জস্যপূর্ণ একটি বাফার আকার এবং নমুনা হারের অনুরোধ করে। এই পরামিতিগুলি ডিভাইস-নির্দিষ্ট এবং নীচে বর্ণিত হিসাবে প্রাপ্ত করা উচিত।
Android 4.2 (API স্তর 17) দিয়ে শুরু করে, একটি অ্যাপ্লিকেশন প্ল্যাটফর্ম নেটিভ বা সর্বোত্তম আউটপুট নমুনা হার এবং ডিভাইসের প্রাথমিক আউটপুট স্ট্রীমের জন্য বাফার আকারের জন্য অনুসন্ধান করতে পারে। এইমাত্র উল্লিখিত বৈশিষ্ট্য পরীক্ষার সাথে মিলিত হলে, একটি অ্যাপ এখন সমর্থন দাবি করে এমন ডিভাইসগুলিতে কম লেটেন্সি আউটপুটের জন্য উপযুক্তভাবে কনফিগার করতে পারে।
Android 4.2 (API লেভেল 17) এবং তার আগের জন্য, কম লেটেন্সির জন্য দুই বা তার বেশি একটি বাফার কাউন্ট প্রয়োজন। Android 4.3 (API লেভেল 18) দিয়ে শুরু করে, কম লেটেন্সির জন্য একটি বাফার কাউন্ট যথেষ্ট।
আউটপুট প্রভাবগুলির জন্য সমস্ত OpenSL ES ইন্টারফেস নিম্ন লেটেন্সি পথকে বাধা দেয়।
প্রস্তাবিত ক্রম নিম্নরূপ:
- OpenSL ES ব্যবহার নিশ্চিত করতে API স্তর 9 বা তার বেশি পরীক্ষা করুন।
- এই ধরনের কোড ব্যবহার করে
android.hardware.audio.low_latency
বৈশিষ্ট্যটি পরীক্ষা করুন:কোটলিন
import android.content.pm.PackageManager ... val pm: PackageManager = context.packageManager val claimsFeature: Boolean = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY)
জাভা
import android.content.pm.PackageManager; ... PackageManager pm = getContext().getPackageManager(); boolean claimsFeature = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
-
android.media.AudioManager.getProperty()
ব্যবহার নিশ্চিত করতে API লেভেল 17 বা তার বেশি পরীক্ষা করুন। - এই ধরনের কোড ব্যবহার করে এই ডিভাইসের প্রাথমিক আউটপুট স্ট্রীমের জন্য নেটিভ বা সর্বোত্তম আউটপুট নমুনা হার এবং বাফার আকার পান: উল্লেখ্য যে
কোটলিন
import android.media.AudioManager ... val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager val sampleRate: String = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE) val framesPerBuffer: String = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)
জাভা
import android.media.AudioManager; ... AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); String sampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
sampleRate
এবংframesPerBuffer
হল স্ট্রিং । প্রথমে null পরীক্ষা করুন এবং তারপরInteger.parseInt()
ব্যবহার করে int-এ রূপান্তর করুন। - PCM বাফার কিউ ডেটা লোকেটার সহ একটি অডিওপ্লেয়ার তৈরি করতে এখন OpenSL ES ব্যবহার করুন।
দ্রষ্টব্য: আপনি আপনার অডিও ডিভাইসে OpenSL ES অডিও অ্যাপ্লিকেশনের জন্য নেটিভ বাফার আকার এবং নমুনা হার নির্ধারণ করতে অডিও বাফার সাইজ পরীক্ষা অ্যাপ ব্যবহার করতে পারেন। অডিও-বাফার-আকারের নমুনা দেখতে আপনি গিটহাব-এও যেতে পারেন।
নিম্ন লেটেন্সি অডিও প্লেয়ারের সংখ্যা সীমিত। আপনার অ্যাপ্লিকেশনের জন্য কয়েকটি অডিও উত্সের প্রয়োজন হলে, অ্যাপ্লিকেশন স্তরে আপনার অডিও মিশ্রিত করার কথা বিবেচনা করুন৷ আপনার কার্যকলাপ থামানো হলে আপনার অডিও প্লেয়ারগুলিকে ধ্বংস করতে ভুলবেন না, কারণ সেগুলি অন্যান্য অ্যাপের সাথে ভাগ করা একটি বিশ্বব্যাপী সম্পদ।
শ্রবণযোগ্য সমস্যা এড়াতে, বাফার কিউ কলব্যাক হ্যান্ডলারকে একটি ছোট এবং অনুমানযোগ্য সময় উইন্ডোর মধ্যে কার্যকর করতে হবে। এটি সাধারণত মিউটেক্স, শর্ত, বা I/O ক্রিয়াকলাপগুলিতে কোনও সীমাহীন ব্লকিং বোঝায়। পরিবর্তে লক , লক এবং টাইমআউট এবং নন-ব্লকিং অ্যালগরিদম সহ অপেক্ষা করার চেষ্টা করুন।
পরবর্তী বাফার (অডিওপ্লেয়ারের জন্য) রেন্ডার করতে বা পূর্ববর্তী বাফার (অডিও রেকর্ডের জন্য) ব্যবহার করার জন্য প্রয়োজনীয় গণনা প্রতিটি কলব্যাকের জন্য প্রায় একই পরিমাণ সময় নিতে হবে। অ্যালগরিদমগুলি এড়িয়ে চলুন যেগুলি একটি অ-নির্ধারিত পরিমাণে কার্যকর হয় বা তাদের গণনার মধ্যে ফেটে যায় । একটি কলব্যাক গণনা বিস্ফোরিত হয় যদি কোনো প্রদত্ত কলব্যাকে CPU সময় ব্যয় করা গড় থেকে উল্লেখযোগ্যভাবে বড় হয়। সংক্ষেপে, আদর্শ হল হ্যান্ডলারের সিপিইউ কার্যকর করার সময় শূন্যের কাছাকাছি বৈচিত্র্য থাকা এবং হ্যান্ডলারের জন্য সীমাহীন সময়ের জন্য ব্লক না করা।
নিম্ন লেটেন্সি অডিও শুধুমাত্র এই আউটপুটগুলির জন্য সম্ভব:
- অন-ডিভাইস স্পিকার।
- তারযুক্ত হেডফোন।
- তারযুক্ত হেডসেট।
- লাইন আউট.
- ইউএসবি ডিজিটাল অডিও ।
কিছু ডিভাইসে, স্পিকার সংশোধন এবং সুরক্ষার জন্য ডিজিটাল সিগন্যাল প্রক্রিয়াকরণের কারণে স্পীকার লেটেন্সি অন্যান্য পাথের তুলনায় বেশি।
অ্যান্ড্রয়েড 5.0 (এপিআই লেভেল 21) অনুযায়ী, নির্বাচিত ডিভাইসগুলিতে নিম্ন লেটেন্সি অডিও ইনপুট সমর্থিত। এই বৈশিষ্ট্যের সুবিধা নিতে, প্রথমে নিশ্চিত করুন যে উপরে বর্ণিত হিসাবে নিম্ন লেটেন্সি আউটপুট উপলব্ধ। নিম্ন লেটেন্সি আউটপুটের ক্ষমতা নিম্ন লেটেন্সি ইনপুট বৈশিষ্ট্যের জন্য একটি পূর্বশর্ত। তারপর, আউটপুটের জন্য ব্যবহার করা হবে একই নমুনা হার এবং বাফার আকার সহ একটি AudioRecorder তৈরি করুন। ইনপুট প্রভাবগুলির জন্য OpenSL ES ইন্টারফেসগুলি নিম্ন লেটেন্সি পাথকে বাধা দেয়। রেকর্ড প্রিসেট SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION
কম বিলম্বের জন্য ব্যবহার করা আবশ্যক; এই প্রিসেটটি ডিভাইস-নির্দিষ্ট ডিজিটাল সিগন্যাল প্রসেসিং অক্ষম করে যা ইনপুট পাথে লেটেন্সি যোগ করতে পারে। রেকর্ড প্রিসেট সম্পর্কে আরও তথ্যের জন্য, উপরে Android কনফিগারেশন ইন্টারফেস বিভাগটি দেখুন।
একযোগে ইনপুট এবং আউটপুটের জন্য, প্রতিটি পাশের জন্য পৃথক বাফার কিউ কমপ্লিশন হ্যান্ডলার ব্যবহার করা হয়। এই কলব্যাকগুলির আপেক্ষিক ক্রম, বা অডিও ঘড়িগুলির সিঙ্ক্রোনাইজেশনের কোনও গ্যারান্টি নেই, এমনকি যখন উভয় পক্ষ একই নমুনা হার ব্যবহার করে। আপনার অ্যাপ্লিকেশন সঠিক বাফার সিঙ্ক্রোনাইজেশন সহ ডেটা বাফার করা উচিত।
সম্ভাব্য স্বাধীন অডিও ঘড়ির একটি ফলাফল হল অ্যাসিঙ্ক্রোনাস নমুনা হার রূপান্তরের প্রয়োজন। অ্যাসিঙ্ক্রোনাস নমুনা হার রূপান্তরের জন্য একটি সহজ (যদিও অডিও মানের জন্য আদর্শ নয়) কৌশল হল একটি শূন্য-ক্রসিং পয়েন্টের কাছে প্রয়োজন অনুসারে নমুনাগুলি নকল করা বা ড্রপ করা৷ আরও পরিশীলিত রূপান্তর সম্ভব।
কর্মক্ষমতা মোড
Android 7.1 (API লেভেল 25) দিয়ে শুরু করে OpenSL ES অডিও পাথের জন্য একটি পারফরম্যান্স মোড নির্দিষ্ট করার একটি উপায় চালু করেছে। বিকল্পগুলি হল:
-
SL_ANDROID_PERFORMANCE_NONE
: কোনো নির্দিষ্ট কর্মক্ষমতা প্রয়োজন নেই। হার্ডওয়্যার এবং সফ্টওয়্যার প্রভাবের অনুমতি দেয়। -
SL_ANDROID_PERFORMANCE_LATENCY
: লেটেন্সিকে অগ্রাধিকার দেওয়া হয়। কোন হার্ডওয়্যার বা সফ্টওয়্যার প্রভাব নেই। এটি ডিফল্ট মোড। -
SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS
: হার্ডওয়্যার এবং সফ্টওয়্যার প্রভাবগুলিকে অনুমতি দেওয়ার সময় লেটেন্সিকে অগ্রাধিকার দেওয়া হয়৷ -
SL_ANDROID_PERFORMANCE_POWER_SAVING
: শক্তি সংরক্ষণকে অগ্রাধিকার দেওয়া হয়েছে। হার্ডওয়্যার এবং সফ্টওয়্যার প্রভাবের অনুমতি দেয়।
দ্রষ্টব্য: আপনার যদি কম লেটেন্সি পাথের প্রয়োজন না হয় এবং আপনি ডিভাইসের অন্তর্নির্মিত অডিও প্রভাবগুলির সুবিধা নিতে চান (উদাহরণস্বরূপ ভিডিও প্লেব্যাকের জন্য অ্যাকোস্টিক গুণমান উন্নত করতে), আপনাকে অবশ্যই পারফরম্যান্স মোডটি স্পষ্টভাবে SL_ANDROID_PERFORMANCE_NONE
এ সেট করতে হবে।
কর্মক্ষমতা মোড সেট করতে, আপনাকে অবশ্যই Android কনফিগারেশন ইন্টারফেস ব্যবহার করে SetConfiguration
কল করতে হবে, যেমনটি নীচে দেখানো হয়েছে:
// Obtain the Android configuration interface using a previously configured SLObjectItf. SLAndroidConfigurationItf configItf = nullptr; (*objItf)->GetInterface(objItf, SL_IID_ANDROIDCONFIGURATION, &configItf); // Set the performance mode. SLuint32 performanceMode = SL_ANDROID_PERFORMANCE_NONE; result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE, &performanceMode, sizeof(performanceMode));
নিরাপত্তা এবং অনুমতি
যতদূর কে কি করতে পারে, অ্যান্ড্রয়েডে নিরাপত্তা প্রক্রিয়া পর্যায়ে সম্পন্ন করা হয়। জাভা প্রোগ্রামিং ল্যাঙ্গুয়েজ কোড নেটিভ কোডের চেয়ে বেশি কিছু করতে পারে না এবং নেটিভ কোড জাভা প্রোগ্রামিং ল্যাঙ্গুয়েজ কোডের চেয়ে বেশি কিছু করতে পারে না। তাদের মধ্যে পার্থক্য শুধুমাত্র উপলব্ধ APIs.
OpenSL ES ব্যবহার করা অ্যাপ্লিকেশনগুলিকে অবশ্যই অনুরূপ নন-নেটিভ API-এর জন্য প্রয়োজনীয় অনুমতিগুলির জন্য অনুরোধ করতে হবে। উদাহরণস্বরূপ, যদি আপনার অ্যাপ্লিকেশনটি অডিও রেকর্ড করে, তাহলে এটির android.permission.RECORD_AUDIO
অনুমতি প্রয়োজন৷ যে অ্যাপ্লিকেশানগুলি অডিও ইফেক্ট ব্যবহার করে তাদের android.permission.MODIFY_AUDIO_SETTINGS
প্রয়োজন৷ নেটওয়ার্ক ইউআরআই রিসোর্স চালানোর জন্য অ্যাপ্লিকেশনগুলির android.permission.NETWORK
প্রয়োজন৷ আরও তথ্যের জন্য সিস্টেম অনুমতিগুলির সাথে কাজ করা দেখুন।
প্ল্যাটফর্ম সংস্করণ এবং বাস্তবায়নের উপর নির্ভর করে, মিডিয়া বিষয়বস্তু পার্সার এবং সফ্টওয়্যার কোডেকগুলি Android অ্যাপ্লিকেশনের প্রেক্ষাপটে চলতে পারে যা OpenSL ES কল করে (হার্ডওয়্যার কোডেকগুলি বিমূর্ত কিন্তু ডিভাইস-নির্ভর)। পার্সার এবং কোডেক দুর্বলতাগুলিকে কাজে লাগানোর জন্য ডিজাইন করা বিকৃত বিষয়বস্তু একটি পরিচিত আক্রমণ ভেক্টর। আমরা সুপারিশ করি যে আপনি শুধুমাত্র বিশ্বস্ত উত্স থেকে মিডিয়া চালান বা আপনি আপনার অ্যাপ্লিকেশনটিকে এমনভাবে ভাগ করুন যে কোডটি তুলনামূলকভাবে স্যান্ডবক্সযুক্ত পরিবেশে অবিশ্বস্ত উত্স থেকে মিডিয়া পরিচালনা করে৷ উদাহরণস্বরূপ, আপনি একটি পৃথক প্রক্রিয়ায় অবিশ্বস্ত উত্স থেকে মিডিয়া প্রক্রিয়া করতে পারেন। যদিও উভয় প্রক্রিয়া এখনও একই UID-এর অধীনে চলবে, এই বিচ্ছেদ আক্রমণকে আরও কঠিন করে তোলে।