2015年11月21日 星期六

Android - 使用SoundPool播放短音效

有時候我們在寫Android程式時,只是想使用一些短小的音效,
然後利用其做變化來達到不同的效果,例如槍聲,我們只要移用一發的槍聲,
配上次數、間隔、持續時間、頻率(指聲波波長)等,
就可以組成許多不同的槍聲,
這時我們可能就會選擇不用存一堆龐大的音效在手機中,而是存短小的一發槍聲音效就好,以節省記憶體空間。

Android 有一個類別就可以很好地提供這樣的需求,
SoundPool,
它可以存放多個音效,選擇要播放的音效,指定左、右聲道音量大小(給耳機用才聽得出來)、播放次數、持續時間等。

下面就來演示一個簡單的範例:

MainActivity.java :
package com.example.gjun.audiopractice;

import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.SeekBar;

public class MainActivity extends ActionBarActivity {
    //本例適用於智小音樂,可調節聲音大小及播放時間(只是拉長波型)

    // 控制左右聲道用的SeekBar元件
    private SeekBar volume_left, volume_right;
    // 左右聲道音量,0.0F ~ 1.0F
    private float leftVolume = 1.0F, rightVolume = 1.0F;
    //存放音樂的Pool
    private SoundPool soundPool;
    private int soundId01, soundId02;
    //現在或最近一次播放的soudPool音效ID
    private int playing;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //獲取元件
        volume_left = (SeekBar) findViewById(R.id.volume_left);
        volume_right = (SeekBar) findViewById(R.id.volume_right);

        // 建立控制左右聲道的進度改變監聽物件
        SeekBar.OnSeekBarChangeListener listener =
                new SeekBar.OnSeekBarChangeListener() {
                    @Override
                    public void onProgressChanged(SeekBar seekBar,
                                                  int progress, boolean fromUser) {
                        switch (seekBar.getId()){
                            // 改變左聲道音量
                            case R.id.volume_left :
                                leftVolume = progress/10.0F;
                                break;
                            // 改變右聲道音量
                            case R.id.volume_right :
                                rightVolume = progress/10.0F;
                                break;
                        }
                        // 設定指定編號的左右聲道音量
                        soundPool.setVolume(playing,leftVolume,rightVolume);
                    }

                    @Override
                    public void onStartTrackingTouch(SeekBar seekBar) {}

                    @Override
                    public void onStopTrackingTouch(SeekBar seekBar) {}
                };
        //設置SeekBar的Listener
        volume_left.setOnSeekBarChangeListener(listener);
        volume_right.setOnSeekBarChangeListener(listener);

        // 建立SoundPool物件
        // 第一個參數設定音效最大數量
        // 第二個參數設定音效種類,通常指定為AudioManager.STREAM_MUSIC
        // 第三個參數設定播放音質,目前沒有作用
        // 載入指定資源編號的音樂並取得編號,第三個參數目前沒有作用
        soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC,0);
        soundId01 = soundPool.load(this,R.raw.sound01,0);
        soundId02 = soundPool.load(this,R.raw.sound02,0);
    }

    //以下按下播放事件用activity_main.xml綁定在元件的click事件上
    public void clickPlay01(View view) {
        // 播放第一個音效
        soundPool.play(soundId01,leftVolume,rightVolume,0,0,1.0F);
        playing = soundId01;
    }

    public void clickPlay02(View view) {
        // 播放第二個音效
        soundPool.play(soundId02,leftVolume,rightVolume,0,0,1.0F);
        playing = soundId02;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}


activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TableLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/retangle_drawable"
        android:layout_margin="12dp"
        android:padding="8dp"
        android:stretchColumns="1" >

        <TableRow
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp" >
            <TextView android:text="LEFT" />

            <SeekBar
                android:id="@+id/volume_left"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:max="10"
                android:progress="10" />
        </TableRow>

        <TableRow
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp" >
            <TextView android:text="RIGHT" />

            <SeekBar
                android:id="@+id/volume_right"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:max="10"
                android:progress="10" />
        </TableRow>
    </TableLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/retangle_drawable"
        android:layout_margin="12dp"
        android:padding="6sp" >
        <ImageButton
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/play_icon"
            android:onClick="clickPlay01" />
        <ImageButton
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/play_icon"
            android:onClick="clickPlay02" />
    </LinearLayout>

</LinearLayout>

AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gjun.audiopractice" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

程式碼下載:
AudioPractice.7z

沒有留言 :

張貼留言