Android audio: tone change

The Android documentation for SoundPool says: "The application can also change the pitch by adjusting the real-time playback speed for Doppler effects or synthesis effects." So I tried to do this using the setRate method to seamlessly transition from one note to another, but the result is terrible: the variation in sound is very broken. 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); } 
+6
source share
2 answers

Although you can use setRate() in the Androids documentation to create Doppler effects, I would not rely on a fast or good enough implementation on every Android device.

Available audio chips require a fixed sampling frequency of 44 kHz or 48 kHz. The conversion of the sampling frequency (i.e., the change in pitch), therefore, must be performed in software. Since this includes a low-level crunch, I'm sure it is implemented by the device manufacturer, not Google. Given the wide range of Android device manufacturers and often low-cost hardware, there are, of course, many sample rate conversion programs. Faster, slower. Some are smooth, some are torn.

What happens when the conversion speed changes during playback? If the algorithm does not match the pieces exactly together, there may be a slight crack in your sound reproduction. You change the conversion rate every 10 milliseconds. If there is a crack every 10 ms, which corresponds to a frequency of 100 Hz, which itself is a tone. This is probably what you hear as β€œtattered.”

In general, I don’t think it is possible to emulate musical instruments in real time on a wide range of Android devices using the high-level Android API. A natural application can be quite fast though.

+13
source

After you all figured out, I decided to go with SoundPool to change Pitch. A playback speed of 2.0 causes the sound to play at a frequency twice that of its original, and a playback speed of 0.5 makes it play half the original frequency. The playback speed range is from 0.5 to 2.0. But he worked with frequencies lower and higher than 0.5 and 2.0.

I submit my working code,

but as its just for demo purpose, here you need to manually change the "playback speed" every time you install the application, for example: "sp.play (explosion, 1,1,0,0,1,5f)", here " 1.5f "is the playback speed. You can easily create an EditView or something similar to set the value of the playback speed at runtime.

In this application, you just need to click on the application screen to play music with the set playback speed.

 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); } } } 
0
source

Source: https://habr.com/ru/post/900341/


All Articles