ضبط صدا در اندروید با کلاس AudioRecord


چگونه با استفاده از کلاس AudioRecord در اندروید صدا را ضبط کنیم؟

برای ضبط صدا در اندروید سه راه وجود دارد. استفاده از کلاس MediaRecorder، استفاده از intent با مشخص نمودن ACTION_GET_CONTENT در متد setAction و استفاده از کلاس AudioRecord.

مقایسه روش های در دسترس برای ضبط صدا

استفاده از کلاس AudioRecord در مقایسه با دو روش دیگر انعطاف پذیر تر می باشد. در این روش به streamِ خام صدای در حال ضبط دسترسی داریم. اما در این روش تعداد زیادی متد از پیش ساخته شده نداریم و مجبوریم خود متدهای لازم را پیاده سازی کنیم. مثلا در این روش فشرده سازی فایل مربوطه به شکل خودکار انجام نمی شود. در صورتی که با استفاده از MediaRecorder روش کار حاضر و آماده ست اما آزادی عمل چندانی نداریم.

چگونه از کلاس AudioRecorder استفاده کنیم؟

اصول استفاده از کلاس AudioRecord ساده است. Objectی از کلاس AudioRecord ایجاد کرده و تنظیمات مورد نظر را روی آن اعمال می کنیم. اما پیش از ساخت object باید مواردی را مهیا کنیم تا به constructorِ این کلاس پاس دهیم.

قدم اول : تعیین منبع برای ضبط صدا

اولین قدم تعیین منبع مورد استفاده ست. مقادیری که استفاده می کنیم مثل حالتی ست که از MediaRecorder استفاده می کنیم.

int audioSource = MediaRecorder.AudioSource.MIC;

قدم دوم : تنظیم sample rate و توضیح مختصری درباره آن

پارامتر بعدی که باید ست شود، sample rate مربوط به صدای در حال ضبط است. واحد اندازه گیری sample rate ، هرتز می باشد. MediaRecorder از صدایی نمونه برداری می کند که در مقدار 8kHz یا 8000Hz باشد.

Sample rate به زبان ساده

 تمام صداهای موجود ارتعاشات مخصوص به خود را دارند. برای ضبط صداهای موجود در بازه شنوایی انسان نیاز است به تعداد مشخصی در ثانیه از آنها نمونه برداری شود. تبدیل صدا به بیت در محدوده هرتز sample rate نام دارد.

دیوایس صدا را به صورت تعداد زیادی صفر و یک کدگذاری و پردازش می کند. پروسه ی تبدیل صدا به بایت sample rate نام دارد که مشخص می کند این کار با چه فرکانسی انجام می گیرد.

صدای ضبط شده روی سی دی ها معمولا در 44.1kHz یا 44100Hz هستند. هرتز نمونه های موجود از صدا در زمان یک ثانیه ست. همان طور که می دانید هرتز واحد اندازه گیری فرکانس در SI می باشد و مفهوم آن تعداد دور در مدت زمان یک ثانیه ست.

Headset در دیوایس های مختلف sample rate های متفاوتی دارد.

در برنامه ی مورد نظر ما، عملیات مربوط به sample rate در 11025 Hz انجام می شود. یکی از فرکانس های مورد استفاده برای sample rate همین مقدار می باشد.

int sampleRateInHz = 11025;

قدم سوم : تنظیم کانال ها

در قدم بعدی باید تعداد کانال های مورد نیاز برای ضبط صدا را مشخص کنیم. ثابت های مورد نیاز برای این منظور، در کلاس AudioFormat تعریف شده اند :

  • AudioFormat.ENCODING_DEFAULT
  • AudioFormat.ENCODING_INVALID
  • AudioFormat.ENCODING_PCM_16BIT
  • AudioFormat.ENCODING_PCM_8 BIT

از میان آنها به دو مورد PCM 16bit  و PCM 8bit نیاز داریم. PCM مخفف Pulse Code Modulation می باشد که برای نمونه خام صدایی که در حال ضبط می باشد، ضروری ست. می توانیم وضوح صدای ضبط شده را روی 16bit یا 8bit ست کنیم.

پردازش و فضای مورد نیاز برای 16bit در حافظه بیشتر است. به این ترتیب خروجی صدای ضبط شده وضوح بیشتری خواهد داشت. در این مثال از 16bit استفاده می کنیم.

int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

قدم چهارم : سایز بافر و ساخت object جدیدی از کلاس AudioRecord

در آخر باید سایز بافر مورد استفاده را مشخص کنیم. با استفاده از متد getMinBufferSize در کلاس AudioRecord می توانیم حداقل بافر مورد نیاز را ست کنیم. مواردی که تا این مرحله تنظیم کردیم را بعنوان پارامتر ورودی به این متد پاس می دهیم:

int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig,~ audioFormat);

در این مرحله می توانیم objectی از کلاس AudioRecord بسازیم.

AudioRecord audioRecord = new AudioRecord(audioSource, sampleRateInHz, channelConfig,~ audioFormat, bufferSizeInBytes);

قدم پنجم : تبدیل صدای ضبط شده به فایل و ذخیره سازی

کلاس AudioRecord صدای ضبط شده را در هیچ آدرسی ذخیره نمی کند. این بخش از کار باید به طور دستی در برنامه پیاده سازی شود. پس در این مرحله باید صدای ضبط شده را به فایل تبدیل کنیم.

برای این منظور فایلی می سازیم.

File recordingFile;
File path = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.apress.proandroidmedia.ch07w .altaudiorecorder /files/"); path.mkdirs(); 
try {
recordingFile = File.createTempFile("recording", ".pcm", path); } 
catch (IOException e1) {
throw new RuntimeException("Couldn't create file on SD card", e);

در ادامه برای این فایل OutputStream ایجاد می کنیم و هم چنین BufferedOutputStream و DataOutputStream را برای عملکرد و پرفورمنس بهتر استفاده می کنیم.

DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new^ FileOutputStream(recordingFile)));

می توانیم sampleهای صدای در حال ضبط را دریافت و به فایل تبدیل کنیم. با آرایه ای از نوع short صدای ضبط شده ای که در objectِ AudioRecord قرار دارد را ذخیره می کنیم.

آرایه ی مورد نظر باید کوچک تر از بافری باشد که در اختیار AudioRecord قرار دارد. به این ترتیب بافر قبل از تمام شدن مرحله ی read سر ریز نمی کند.

برای اطمینان از کوچک تر بودن سایز آرایه نسبت به بافر، سایز آرایه را برابر با یک چهارم سایزِ بافر قرار می دهیم.

short[] buffer = new short[bufferSize/4];

به واسطه ی objectی که از AudioRecord ساختیم، متدِ startRecording را می سازیم.

audioRecord.startRecording();

پس از شروع ضبط صدا می توانیم با استفاده از یک حلقه، با انجام پروسه ی read روی objectِ ساخته شده از AudioRecord و write آن روی آرایه و در نهایت نوشتن این آرایه (انجام عملیات write) روی DataOutputStream در نهایت فایلی از صدای در حال ضبط بسازیم.

int bufferReadResult = audioRecord.read(buffer, 0, bufferSize/4); 
for (int i = 0; i < bufferReadResult; i++) 
dos.writeShort(buffer[i]);
audioRecord.stop(); 
dos.close();

پس از اتمام پروسه هایی که توضیح دادیم کار با objectِ AudioRecord تمام می شود و می توانیم متد stop را از این کلاس صدا بزنیم. هم چنین کارمان با dataOutputStream به پایان رسیده و نمونه ی این کلاس را هم با صدا زدن متد close می بندیم.

حتما به این نکته توجه داشته باشید که این پروسه باید در threadی جداگانه انجام شود تا رابط کاربری مختل نشده و main thread متوقف نشود.

به این پست امتیاز دهید

روی ستاره های کلیک کنید و امتیاز بدید

میانگین امتیاز / 5. تعداد:

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *




Enter Captcha Here : *

Reload Image