Search This Blog

Support my cause by downloading

Monday, 22 July 2013

Sound Pool Tutorial in Android : changing pitch of an sound file

SoundPool provide a frequency range to change the pitch of voice. This tutorial address the sound pool features. After reading this tutorial you will be able to answer these question

1) What is soundPool?
2) Why we use it?
3) How to change pitch of sound file through frequency?

How to prepare a simple sound Pool?


Sound Pool : A SoundPool is a collection of samples that can be loaded into memory from a resource inside the APK or from a file in the file system. The SoundPool library uses the MediaPlayer service to decode the audio into a raw 16-bit PCM mono or stereo stream. This allows applications to ship with compressed streams without having to suffer the CPU load and latency of decompressing during playback.

Creating simple sound pool with one sound file. Keep your sound file inside raw folder

SoundPool soundPool = new SoundPool(50, AudioManager.STREAM_MUSIC, 0);

50 is the number of repeat cycle, 0 is srcquality

Now load one sound file and wait until load finish using OnLoadCompleteListener.

        /** Sound ID for Later handling of sound pool **/
        soundId = soundPool.load(this, R.raw.sounds, 1);
        soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
            @Override
            public void onLoadComplete(SoundPool arg0, int arg1, int arg2) {
                streamId = soundPool.play(soundId, 1, 1, 1, 3, pitch);
                soundPool.setLoop(streamId, -1);
                Log.e("TAG", String.valueOf(streamId));
            }
        });

This tutorial has two button two increase and decrease frequency rate. Just See the complete code

XML


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".PitchActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="147dp"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/plus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_marginLeft="147dp"
        android:layout_marginTop="35dp"
        android:text="+" />

    <Button
        android:id="@+id/minus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/plus"
        android:layout_below="@+id/plus"
        android:layout_marginTop="41dp"
        android:text="-" />

</RelativeLayout>

Activity


package com.pitch;

import android.app.Activity;
import android.media.AudioManager;
import android.media.SoundPool;
import android.media.SoundPool.OnLoadCompleteListener;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

public class PitchActivity extends Activity implements OnClickListener {
    TextView mtxView;
    SoundPool soundPool;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pitch);
        mtxView = (TextView) findViewById(R.id.textView1);
        mtxView.setText("Current Pitch=0.5");
        findViewById(R.id.plus).setOnClickListener(this);
        findViewById(R.id.minus).setOnClickListener(this);
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
        soundPool = new SoundPool(50, AudioManager.STREAM_MUSIC, 0);
        /** Sound ID for Later handling of sound pool **/
        soundId = soundPool.load(this, R.raw.sounds, 1);
        soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
            @Override
            public void onLoadComplete(SoundPool arg0, int arg1, int arg2) {
                streamId = soundPool.play(soundId, 1, 1, 1, 3, pitch);
                soundPool.setLoop(streamId, -1);
                Log.e("TAG", String.valueOf(streamId));
            }
        });
    }

    int streamId = 0;
    int soundId = -1;
    float pitch = 01f;

    @Override
    public void onClick(View arg0) {
        switch (arg0.getId()) {
        case R.id.minus:
            pitch -= 0.5;
            mtxView.setText("Current Pitch=" + pitch);
            soundPool.setRate(streamId, pitch);
            break;
        case R.id.plus:
            pitch += 0.5;
            mtxView.setText("Current Pitch=" + pitch);
            soundPool.setRate(streamId, pitch);
            break;
        default:
            break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            soundPool.pause(streamId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}



Important Points : your file not be bigger than 32 because Android Audio Framework allows only 32 tracks(includes playing/stopped/paused/...) per mixer thread at the same time. If it exceed then you will get error code -12

AudioFlinger could not create track, status: -12
Error creating AudioTrack

Reference Link

Android Developer

Android News and source code