Dạo gần lướt Tiktok thấy có mấy idol thể hiện kỹ năng chơi đàn trên điện thoại. Mình nhìn thấy rất là hâm mộ. Nhưng mà mình biết, mình không có năng khiếu nghệ thuật, chân tay thô cứng nên thay vì đi học đánh đàn, sẽ tự xây dựng một ứng dụng đàn Piano của riêng mình.
Các ứng dụng này về cơ bản sử dụng SoundPool API của Android để xử lý các giai điệu nhạc ngắn. Ngoài Piano ra, bạn có thể tạo âm thanh của Violin hoặc Xylophone.
Chúng ta bắt đầu nhé!
Nội dung chính của bài viết
1. Android SoundPool
Trong hướng dẫn dưới đây, mình sẽ chỉ cho các bạn cách tạo một ứng dụng Piano bằng việc sử dụng SoundPool trong Android API.
Trước tiên, bạn cần có kiến thức cơ bản về ConstraintLayout để có thể hiểu và thiết kế giao diện các bàn phím Piano.
2. Trước tiên cần chuẩn bị
- Windows 7 hoặc cao hơn / Mac OS (Mavericks or higher) với ít nhất 4GB RAM
- Android Studio (với SDK và API bản mới nhất) và JAVA đã cài đặt trên hệ thống của bạn. (💥 Tham khảo cách cài đặt Android Studio nếu chưa rõ nhé)
- File hiệu ứng âm thanh mô phỏng các nốt nhạc: Download.
3. Những tính năng chính của đàn Piano?
Ứng dụng mà mình giới thiệu trong bài này sẽ gồm 14 buttons, mỗi button được gán một onClick()
Listener và phát ra âm thanh bằng cách sử dụng SoundPool API. Các button và vị trí của chúng được thiết lập bằng cách sử dụng ConstraintLayout
Ứng dụng gồm 8 buttons có màu trắng với âm thanh C, D, E, F, G, A và B và 5 nút màu đen tương ứng với âm C #, D #, F #, G # , A # và 1 âm C # khác.
4. Dự án gồm các files chính:
- activity_main.xml
- MainActivity.java
- AndroidManifest.xml (No permissions required)
💦 Một vài ứng dụng bạn hứng thú: Tự ứng dụng máy tính bỏ túi Calculator
5. Các bước thực hiện
#Thiết kế giao diện layout
Bước 1: Mở Android Studio và tạo một dự án mới với tên là “My Piano”, tạo một class với tên là MainAvticity.java.
Bước 2: Trong activity_main.xml
, xóa “Hello World” TextView và thêm vào 8 buttons.Về cơ bản mỗi button sẽ có thông số như bên dưới:
<Button android:id="@+id/c" android:layout_width="match_parent" android:layout_height="63dp" android:text="C" android:textSize="30sp" android:textStyle="bold" android:textAlignment="textStart" android:background="#ffffff" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" android:onClick="playC" />
Bước 3: Tương tự cho 6 buttons vào layout với nút C # đầu tiên giữa các nút màu trắng C và D. Bạn có thể liên kết nó với nút tiếp theo, ví dụ: D # bên dưới C # và ở cuối của parent.
<Button android:id="@+id/ds" android:layout_width="187dp" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="D#" android:textAlignment="textStart" android:textSize="20sp" android:textStyle="bold" android:background="#000000" android:textColor="#ffffff" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/cs" android:onClick="playDS"/>
#Tìm hiểu Android SoundPool
Tại sao cần sử dụng SoundPool?
Đầu tiên, SoundPool trong Android có thể phát các tập tin audio cho các ứng dụng. Bên cạnh đó, nó cũng có thể quản lý số luồng âm thanh được hiển thị cùng một lúc(với trường hợp nhiều phím được ấn cùng một lúc).
Đến đây bạn có thể băn khoăn sao không sử dụng MediaPlayer API thay thế ?
Bởi vì nếu dùng MediaPlayer bạn sẽ không thể quản lý nhiều luồng âm thanh giống như SounPool. Lý do mà mình khuyên bạn chọn SoundPool là vì vậy.
Trong Android SoundPool bạn thực sự có thể kiểm soát âm lượng của loa trái và phải, gán quyền ưu tiên (Priority) cho 1 file âm thanh cụ thể , Loop một file âm thanh và điều chỉnh tốc độ chơi của nó.
#Sử dụng SoundPool để tạo âm thanh cho ứng dụng
Tiếp theo chúng ta sẽ điều chỉnh các thông số của Android SoundPool bằng cách sử dụng những biến khác nhau như dưới đây:
private float LEFT_VOL = 1.0f; private float RIGHT_VOL = 1.0f; private int PRIORITY = 1; private int LOOP = 0; private float RATE = 1.0f;
Tiếp theo tạo SoundPool constructor theo đoạn code dưới đây:
mSoundPool = new SoundPool(10, AudioManager.STREAM_MUSIC,0); SoundPool(int maxStreams, int streamType, int srcQuality)
Đối với mỗi biến âm được tạo ở trên, gắn nó với âm thanh tương ứng. Đoạn code sẽ như sau:
csound = mSoundPool.load(getApplicationContext(),R.raw.c,1); dsound = mSoundPool.load(getApplicationContext(),R.raw.d,1);
Bây giờ tất cả những gì bạn cần làm là tạo một onClick()
Listenner cho mỗi button như trong tệp activity_main.xml ở trên.
Cách làm cực kì đơn giản chỉ cần sử dụng phương thức play trong lớp Android SoundPool như đoạn code cho button C dưới đây
public void playC(View v){ mSoundPool.play(csound,LEFT_VOL,RIGHT_VOL,PRIORITY,LOOP,RATE); }
Đoạn code cho MainActivity.java file sẽ như thế này:
public class MainActivity extends AppCompatActivity { private SoundPool mSoundPool; private int csound; private int dsound; private int esound; private int fsound; private int gsound; private int asound; private int bsound; private int ccsound; private int cssound; private int csssound; private int dssound; private int gssound; private int assound; private int fssound; private float LEFT_VOL = 1.0 f; private float RIGHT_VOL = 1.0 f; private int PRIORITY = 1; private int LOOP = 0; private float RATE = 1.0 f; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSoundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0); csound = mSoundPool.load(getApplicationContext(), R.raw.c, 1); dsound = mSoundPool.load(getApplicationContext(), R.raw.d, 1); esound = mSoundPool.load(getApplicationContext(), R.raw.e, 1); fsound = mSoundPool.load(getApplicationContext(), R.raw.f, 1); gsound = mSoundPool.load(getApplicationContext(), R.raw.g, 1); asound = mSoundPool.load(getApplicationContext(), R.raw.a, 1); bsound = mSoundPool.load(getApplicationContext(), R.raw.b, 1); cssound = mSoundPool.load(getApplicationContext(), R.raw.c_hash, 1); csssound = mSoundPool.load(getApplicationContext(), R.raw.c_hash, 1); ccsound = mSoundPool.load(getApplicationContext(), R.raw.c2, 1); assound = mSoundPool.load(getApplicationContext(), R.raw.a_hash, 1); fssound = mSoundPool.load(getApplicationContext(), R.raw.f_hash, 1); gssound = mSoundPool.load(getApplicationContext(), R.raw.g_hash, 1); dssound = mSoundPool.load(getApplicationContext(), R.raw.d_hash, 1); } public void playC(View v) { mSoundPool.play(csound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playD(View v) { mSoundPool.play(dsound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playE(View v) { mSoundPool.play(esound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playF(View v) { mSoundPool.play(fsound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playG(View v) { mSoundPool.play(gsound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playA(View v) { mSoundPool.play(asound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playB(View v) { mSoundPool.play(bsound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playCC(View v) { mSoundPool.play(ccsound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playCS(View v) { mSoundPool.play(cssound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playDS(View v) { mSoundPool.play(dssound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playFS(View v) { mSoundPool.play(fssound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playGS(View v) { mSoundPool.play(gssound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playAS(View v) { mSoundPool.play(assound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } public void playCSS(View v) { mSoundPool.play(csssound, LEFT_VOL, RIGHT_VOL, PRIORITY, LOOP, RATE); } }
Tạm kết
Cuối cùng, đã đến lúc tận hưởng thành quả !
Chạy ứng dụng vừa mới tạo trên thiết bị di động của bạn, chơi và thưởng thức những giai điệu du dương do chính mình tạo ra bởi Android SoundPool.
Các bạn có thể download toàn bộ source code của bài viết hướng dẫn tại đây
Bạn thấy thế nào về trải nghiệm này? Chia sẻ ngay với mình ở phần nhận xét bên dưới để khiến cho trải nghiệm chơi nhạc của bạn ngày một thú vị hơn nhé !
W/SoundPool: sample 1 not READY
cho em hỏi chạy soundpool mà hiện log kia thì phải khắc phục ntn ạ?
em cảm ơn!
Bạn có thể đợi cho SoundPool khởi tạo xong nhé. Sử dụng callback này: SoundPool.setOnLoadCompleteListener. Cái này giống như bạn khởi tạo sử dụng camera vậy