Phát hiệu ứng âm thanh trong Android với SoundPool
1. SoundPool & AudioManager
Trước hết tôi đặt ra một tình huống, bạn đang tạo một trò chơi, nó phát ra các âm thanh chẳng hạn như tiếng súng, tiếng bom, đó là các hiệu ứng âm thanh trong trò chơi. Android cung cấp cho bạn lớp SoundPool, nó giống như một bể chứa các nguồn nhạc và sẵn sàng phát ra khi có yêu cầu.
SoundPool chứa một tập hợp các nguồn nhạc, nguồn âm có thể từ file nhạc trong ứng dụng hoặc trong file hệ thống,.. SoundPool hỗ trợ phát đồng loạt nhiều nguồn nhạc cùng một lúc.
SourcePool sử dụng MediaPlayer service để phát ra âm thanh.
SoundPool chứa một tập hợp các nguồn nhạc, nguồn âm có thể từ file nhạc trong ứng dụng hoặc trong file hệ thống,.. SoundPool hỗ trợ phát đồng loạt nhiều nguồn nhạc cùng một lúc.
SourcePool sử dụng MediaPlayer service để phát ra âm thanh.
Bạn có thể chỉ định để SoundPool phát ra âm thanh tại stream (luồng) cụ thể. Có một số kiểu stream sau:
Loại luồng âm thanh | Mô tả |
AudioManager.STREAM_ALARM | Các dòng âm thanh cho báo động |
AudioManager.STREAM DTMF | Các dòng âm thanh cho DTMF |
AudioManager.STREAM_MUSIC | Các dòng âm thanh để phát lại âm nhạc |
AudioManager.STREAM_NOTIFICATION | Các dòng âm thanh cho thông báo |
AudioManager.STREAM_RING | Các dòng âm thanh cho điện thoại reo |
AudioManager.STREAM_SYSTEM | Các dòng âm thanh cho âm thanh hệ thống |
AudioManager.STREAM_VOICE_CALL | Các dòng âm thanh cho các cuộc gọi điện thoại |
AudioManager cho phép bạn điều chỉnh âm lượng trên các luồng (stream) âm thanh khác nhau. Chẳng hạn bạn đang nghe nhạc bài hát trên thiết bị đồng thời chơi Game, bạn có thể thay đổi âm lượng của Game mà không ảnh hưởng tới âm lượng của bài hát.
Một vấn đề khác được đề cập là thiết bị âm thanh sẽ phát ra âm thanh.
Sử dụng STREAM_MUSIC âm thanh sẽ được phát ra thông qua một thiết bị âm thanh (loa điện thoại, tai nghe, bluetooth loa hay cái gì khác) kết nối với điện thoại.
Sử dụng STREAM_RING âm thanh sẽ được phát ra thông qua tất cả các thiết bị âm thanh kết nối với điện thoại. Hành vi này có thể khác nhau đối với mỗi thiết bị.
Sử dụng STREAM_MUSIC âm thanh sẽ được phát ra thông qua một thiết bị âm thanh (loa điện thoại, tai nghe, bluetooth loa hay cái gì khác) kết nối với điện thoại.
Sử dụng STREAM_RING âm thanh sẽ được phát ra thông qua tất cả các thiết bị âm thanh kết nối với điện thoại. Hành vi này có thể khác nhau đối với mỗi thiết bị.
SoundPool API:
Phương thức | Mô tả |
int play(int soundID, float leftVolume, float rightVolume,
int priority, int loop, float rate) | Phát một nguồn nhạc, mà trả về một số là ID của luồng âm đang phát (streamID). |
void pause(int streamID) | Tạm dừng luồng âm đang phát có ID là streamID. |
void stop(int streamID) | Ngừng luồng âm ứng với streamID. |
void setVolume(int streamID, float leftVolume, float rightVolume) | Sét đặt âm lượng cho luồng âm với ID là streamID |
void setLoop(int streamID, int loop) | Sét đặt số lần phát lại luồng âm với ID là streamID. |
2. Ví dụ với SoundPool
Tạo mới một project SoundPoolDemo.
- Name: SoundPoolDemo
- Package name: org.o7planning.soundpooldemo
Tạo thư mục raw là con của thư mục res. Copy 2 file nhạc vào thư mục raw, ở đây tôi copy 2 file mô phỏng âm thanh vật thể bị phá hủy (destroy.wav) và âm thanh của tiếng súng (gun.wav). Chú ý bạn có thể sử dụng file nhạc đuôi mp3 hoặc wav.
Giao diện ứng dụng Demo.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button_destroy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="50dp"
android:text="Destroy"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button_gun"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="50dp"
android:text="Gun"
app:layout_constraintStart_toEndOf="@+id/button_destroy"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package org.o7planning.soundpooldemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private SoundPool soundPool;
private AudioManager audioManager;
private Button buttonDestroy;
private Button buttonGun;
// Maximumn sound stream.
private static final int MAX_STREAMS = 5;
// Stream type.
private static final int streamType = AudioManager.STREAM_MUSIC;
private boolean loaded;
private int soundIdDestroy;
private int soundIdGun;
private float volume;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.buttonDestroy = (Button) this.findViewById(R.id.button_destroy);
this.buttonGun = (Button) this.findViewById(R.id.button_gun);
this.buttonDestroy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
playSoundDestroy();
}
});
this.buttonGun.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
playSoundGun();
}
});
// AudioManager audio settings for adjusting the volume
audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
// Current volumn Index of particular stream type.
float currentVolumeIndex = (float) audioManager.getStreamVolume(streamType);
// Get the maximum volume index for a particular stream type.
float maxVolumeIndex = (float) audioManager.getStreamMaxVolume(streamType);
// Volumn (0 --> 1)
this.volume = currentVolumeIndex / maxVolumeIndex;
// Suggests an audio stream whose volume should be changed by
// the hardware volume controls.
this.setVolumeControlStream(streamType);
// For Android SDK >= 21
if (Build.VERSION.SDK_INT >= 21 ) {
AudioAttributes audioAttrib = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
SoundPool.Builder builder= new SoundPool.Builder();
builder.setAudioAttributes(audioAttrib).setMaxStreams(MAX_STREAMS);
this.soundPool = builder.build();
}
// for Android SDK < 21
else {
// SoundPool(int maxStreams, int streamType, int srcQuality)
this.soundPool = new SoundPool(MAX_STREAMS, AudioManager.STREAM_MUSIC, 0);
}
// When Sound Pool load complete.
this.soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
loaded = true;
}
});
// Load sound file (destroy.wav) into SoundPool.
this.soundIdDestroy = this.soundPool.load(this, R.raw.destroy,1);
// Load sound file (gun.wav) into SoundPool.
this.soundIdGun = this.soundPool.load(this, R.raw.gun,1);
}
// When users click on the button "Gun"
public void playSoundGun( ) {
if(loaded) {
float leftVolumn = volume;
float rightVolumn = volume;
// Play sound of gunfire. Returns the ID of the new stream.
int streamId = this.soundPool.play(this.soundIdGun,leftVolumn, rightVolumn, 1, 0, 1f);
}
}
// When users click on the button "Destroy"
public void playSoundDestroy( ) {
if(loaded) {
float leftVolumn = volume;
float rightVolumn = volume;
// Play sound objects destroyed. Returns the ID of the new stream.
int streamId = this.soundPool.play(this.soundIdDestroy,leftVolumn, rightVolumn, 1, 0, 1f);
}
}
}
Chạy ứng dụng:
Các hướng dẫn lập trình Android
- Cấu hình Android Emulator trong Android Studio
- Hướng dẫn và ví dụ Android ToggleButton
- Tạo một File Finder Dialog đơn giản trong Android
- Hướng dẫn và ví dụ Android TimePickerDialog
- Hướng dẫn và ví dụ Android DatePickerDialog
- Bắt đầu với Android cần những gì?
- Cài đặt Android Studio trên Windows
- Cài đặt Intel® HAXM cho Android Studio
- Hướng dẫn và ví dụ Android AsyncTask
- Hướng dẫn và ví dụ Android AsyncTaskLoader
- Hướng dẫn lập trình Android cho người mới bắt đầu - Các ví dụ cơ bản
- Làm sao biết số số điện thoại của Android Emulator và thay đổi nó
- Hướng dẫn và ví dụ Android TextInputLayout
- Hướng dẫn và ví dụ Android CardView
- Hướng dẫn và ví dụ Android ViewPager2
- Lấy số điện thoại trong Android sử dụng TelephonyManager
- Hướng dẫn và ví dụ Android Phone Call
- Hướng dẫn và ví dụ Android Wifi Scanning
- Hướng dẫn lập trình Android Game 2D cho người mới bắt đầu
- Hướng dẫn và ví dụ Android DialogFragment
- Hướng dẫn và ví dụ Android CharacterPickerDialog
- Hướng dẫn lập trình Android cho người mới bắt đầu - Hello Android
- Hướng dẫn sử dụng Android Device File Explorer
- Bật tính năng USB Debugging trên thiết bị Android
- Hướng dẫn và ví dụ Android UI Layouts
- Hướng dẫn và ví dụ Android SMS
- Hướng dẫn lập trình Android với Database SQLite
- Hướng dẫn và ví dụ Google Maps Android API
- Hướng dẫn chuyển văn bản thành lời nói trong Android
- Hướng dẫn và ví dụ Android Space
- Hướng dẫn và ví dụ Android Toast
- Tạo một Android Toast tùy biến
- Hướng dẫn và ví dụ Android SnackBar
- Hướng dẫn và ví dụ Android TextView
- Hướng dẫn và ví dụ Android TextClock
- Hướng dẫn và ví dụ Android EditText
- Hướng dẫn và ví dụ Android TextWatcher
- Định dạng số thẻ tín dụng với Android TextWatcher
- Hướng dẫn và ví dụ Android Clipboard
- Tạo một File Chooser đơn giản trong Android
- Hướng dẫn và ví dụ Android AutoCompleteTextView và MultiAutoCompleteTextView
- Hướng dẫn và ví dụ Android ImageView
- Hướng dẫn và ví dụ Android ImageSwitcher
- Hướng dẫn và ví dụ Android ScrollView và HorizontalScrollView
- Hướng dẫn và ví dụ Android WebView
- Hướng dẫn và ví dụ Android SeekBar
- Hướng dẫn và ví dụ Android Dialog
- Hướng dẫn và ví dụ Android AlertDialog
- Hướng dẫn và ví dụ Android RatingBar
- Hướng dẫn và ví dụ Android ProgressBar
- Hướng dẫn và ví dụ Android Spinner
- Hướng dẫn và ví dụ Android Button
- Hướng dẫn và ví dụ Android Switch
- Hướng dẫn và ví dụ Android ImageButton
- Hướng dẫn và ví dụ Android FloatingActionButton
- Hướng dẫn và ví dụ Android CheckBox
- Hướng dẫn và ví dụ Android RadioGroup và RadioButton
- Hướng dẫn và ví dụ Android Chip và ChipGroup
- Sử dụng các tài sản ảnh và biểu tượng của Android Studio
- Thiết lập SD Card cho Android Emulator
- Ví dụ với ChipGroup và các Chip Entry
- Làm sao thêm thư viện bên ngoài vào dự án Android trong Android Studio?
- Làm sao loại bỏ các quyền đã cho phép trên ứng dụng Android
- Làm sao loại bỏ các ứng dụng ra khỏi Android Emulator?
- Hướng dẫn và ví dụ Android LinearLayout
- Hướng dẫn và ví dụ Android TableLayout
- Hướng dẫn và ví dụ Android FrameLayout
- Hướng dẫn và ví dụ Android QuickContactBadge
- Hướng dẫn và ví dụ Android StackView
- Hướng dẫn và ví dụ Android Camera
- Hướng dẫn và ví dụ Android MediaPlayer
- Hướng dẫn và ví dụ Android VideoView
- Phát hiệu ứng âm thanh trong Android với SoundPool
- Hướng dẫn lập trình mạng trong Android - Android Networking
- Hướng dẫn xử lý JSON trong Android
- Lưu trữ dữ liệu trên thiết bị với Android SharedPreferences
- Hướng dẫn lập trình Android với bộ lưu trữ trong (Internal Storage)
- Hướng dẫn lập trình Android với bộ lưu trữ ngoài (External Storage)
- Hướng dẫn sử dụng Intent trong Android
- Ví dụ về một Android Intent tường minh, gọi một Intent khác
- Ví dụ về Android Intent không tường minh, mở một URL, gửi một email
- Hướng dẫn sử dụng Service trong Android
- Hướng dẫn sử dụng thông báo trong Android - Android Notification
- Hướng dẫn và ví dụ Android DatePicker
- Hướng dẫn và ví dụ Android TimePicker
- Hướng dẫn và ví dụ Android Chronometer
- Hướng dẫn và ví dụ Android OptionMenu
- Hướng dẫn và ví dụ Android ContextMenu
- Hướng dẫn và ví dụ Android PopupMenu
- Hướng dẫn và ví dụ Android Fragment
- Hướng dẫn và ví dụ Android ListView
- Android ListView với Checkbox sử dụng ArrayAdapter
- Hướng dẫn và ví dụ Android GridView
Show More