প্রোগ্রামেটিক্যালি টোন তৈরি ও প্লেব্যাক: AudioTrack ব্যবহার
এই উদাহরণটি দেখাবে কীভাবে গাণিতিক ফর্মুলা ব্যবহার করে একটি সাইন ভেইব (sine wave) তৈরি করে এবং AudioTrack-কে মাধ্যমে তা প্লে করা যায়। এটি সিনথেসাইজার, গেম সাউন্ড, বা টেস্ট টোন তৈরির জন্য ব্যবহারী।
পদক্ষেপ ১: প্রজেক্ট তৈরি করুন
Android Studio-তে নতুন প্রজেক্ট শুরু করুন।
পদক্ষেপ ২: লেআউট XML (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<ImageView
android:layout_width="200dp"
android:layout_height="300dp"
android:src="@drawable/ic_music_note_black_24dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Increase volume to hear the generated tone!"
android:textSize="16sp"
android:textStyle="bold|italic" />
</LinearLayout>
পদক্ষেপ ৩: MainActivity.java - টোন জেনারেশন লজিক
import androidx.appcompat.app.AppCompatActivity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Handler;
public class MainActivity extends AppCompatActivity {
private final int duration = 10; // সেকেন্ড
private final int sampleRate = 8000; // Hz
private final int numSamples = duration * sampleRate;
private final double[] sample = new double[numSamples];
private final byte[] generatedSnd = new byte[2 * numSamples]; // 16-bit = 2 bytes
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
new Thread(this::generateAndPlayTone).start();
}
private void generateAndPlayTone() {
genTone();
handler.post(this::playSound);
}
void genTone() {
// 440 Hz (A4 note) সাইন ভেইব জেনারেট
for (int i = 0; i < numSamples; ++i) {
double freqOfTone = 440;
sample[i] = Math.sin(2 * Math.PI * i / (sampleRate / freqOfTone));
}
// Double [-1, 1] → Signed 16-bit PCM bytes
int idx = 0;
for (double dVal : sample) {
short val = (short) (dVal * 32767); // Max 16-bit amplitude
generatedSnd[idx++] = (byte) (val & 0x00FF); // Low byte
generatedSnd[idx++] = (byte) ((val & 0xFF00) >>> 8); // High byte (unsigned shift)
}
}
void playSound() {
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
sampleRate,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
generatedSnd.length,
AudioTrack.MODE_STATIC
);
audioTrack.write(generatedSnd, 0, generatedSnd.length);
audioTrack.play();
}
}
মূল ধারণা ব্যাখ্যা
- Sample Rate: ৮০০০ Hz (টেলিফোন গুণমান), CD গুণমানের জন্য ৪৪১০০ Hz ব্যবহার করুন
- PCM 16-bit: প্রতিটি স্যাম্পল ২ বাইট (-32768 থেকে 32767)
- Little Endian: Low byte প্রথমে, তারপর high byte
- MODE_STATIC: পুরো ডেটা একসাথে লোড হয় (ছোট ডেটার জন্য), MODE_STREAM বড় ডেটার জন্য
উন্নতীকরণ
- বিভিন্ন ফ্রিকোয়েন্সি, কালাব Identité, হারমোনিক্স যোগ করুন
- এনভেলপ (ADSR) অ্যাপ্লাই করুন প্রাকৃতিক সাউন্ডের জন্য
- রিয়েল-টাইম জেনারেশনের জন্য MODE_STREAM ব্যবহার করুন