Reputation: 3739
The Android documentation for SoundPool says "the application can also alter the pitch by adjusting the playback rate in real-time for doppler or synthesis effects". So I tried to do this, using the setRate method to vary smoothly from one note to another, but the result is awful: the sound variation is very ragged. Here is the code I tried. Please tell me if there is a better way.
int streamId = soundPool.play (soundId, 1, 1, 1, 0, 1.0f);
for (float x = 0; x < 1; x += 0.005) {
SystemClock.sleep (10);
soundPool.setRate (streamId, 1 + x);
}
Upvotes: 6
Views: 13006
Reputation: 33534
After trying everything out, i decided to go with SoundPool to change the Pitch, A playback rate of 2.0 causes the sound to play at a freq double its original, and a playback rate of 0.5 causes it to play at half its original frequency. The playback rate range is 0.5 to 2.0. But it did work with freq lower and higher than 0.5 and 2.0.
I am posting my working code,
but as its just for demo purpose, Here you need to Manually change the "playback rate", everytime you install the application for eg: "sp.play(explosion, 1,1,0,0,1.5f)" here "1.5f" is the playback rate. One can easily create an EditView,or something similar to set the value of playback rate at run time.
In this app, you just need to tap on the app's screen to play the music at the set playback rate.
import java.io.IOException;
import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class SoundPoolActivity extends Activity implements OnClickListener {
SoundPool sp;
int explosion = 0;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View v = new View(this);
v.setOnClickListener(this);
setContentView(v);
sp = new SoundPool(1,AudioManager.STREAM_MUSIC,0);
//explosion = sp.load(this, R.raw.hh,0);
explosion = sp.load("/sdcard/hh.m4a",0);
}
public void onClick(View v){
if (explosion!=0){
sp.play(explosion, 1,1,0,0,2.3f);
}
}
}
Upvotes: 0
Reputation: 1105
Even though the Androids documentation suggests that you can use setRate()
to produce doppler effects, I would not rely on a fast or good enough implementation on every android device.
Affordable audio ICs require a fixed sample rate of 44kHz or 48kHz. Sample rate conversion (i.e. pitch modification) therefore has to be done in software. Because this includes low-level number crunching I am sure that this is implemented by the device manufacturer and not by Google. Given the wide variety of Android device manufacturers and the often low-cost hardware used, there are certainly many sample rate conversion implementations out there. Some faster, some slower. Some smooth, some ragged.
What happens when changing the conversion rate during playback? If the algorithm doesn't match the pieces precisely together, there might be a short crack in your audio playback. You change the conversion rate every 10 milliseconds. If there is a crack every 10ms, that corresponds to a frequency of 100Hz which is a tone itself. This is likely to be what you hear as "ragged".
All in all I don't think that it is possible to emulate musical instruments in real-time on a wide range of Android devices using high-level Android API. A native application might be fast enough though.
Upvotes: 13