2011-10-29 76 views
6

SoundPool的Android文档中提到“应用程序还可以通过实时调整播放速率来改变音高,以实现多普勒效应或综合效果”。所以我试图做到这一点,使用setRate方法从一个音符到另一个音符之间平滑地变化,但结果很糟糕:声音变化非常粗糙。这是我试过的代码。请告诉我,如果有更好的方法。Android音频:变化音高

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

改变'1 + x'到'1.0F + x'和(也改变'0.005'到'0.005f' –

+0

这没什么区别。 – Patrick

+0

你如何测试你的代码。如果您使用的是如果您使用的是模拟器,可能问题在于您的主机的声卡,更改播放速度并不是一项简单的任务,可能需要复杂的插值特别是在使用非标准转换速率运行时 – MBober

回答

13

即使机器人会文档建议,你可以用setRate()产生多普勒效应,我不会依赖于每一个Android设备上的快或足够好的实现。

价格合理的音频IC需要44kHz或48kHz的固定采样率。采样率转换(即音调修改)因此必须用软件完成。因为这包括低级别的数字处理,所以我相信这是由设备制造商而不是Google实施的。鉴于Android设备制造商种类繁多,并且使用的是经常使用的低成本硬件,因此肯定会有很多采样率转换实现。一些更快,一些更慢。一些光滑,一些衣衫褴褛。

在播放过程中更改转换率时会发生什么?如果算法不能精确匹配,那么音频播放中可能会出现短暂的裂缝。您每10毫秒更改一次转换率。如果每10ms有一个裂缝,相当于100Hz的频率,这是一种音调本身。这很可能就是你所说的“衣衫褴褛”。总而言之,我不认为可以在使用高级Android API的各种Android设备上实时模拟乐器。尽管如此,本地应用程序可能会很快。

0

试了一切后,我决定使用SoundPool来改变音高,2.0的播放速度会导致声音以原来的两倍频率播放,0.5的播放速度会导致其播放一半原始频率。播放速率范围是0.5到2.0。 但它的确适用于低于和高于0.5和2.0的频率。

我张贴我的工作代码,

但由于其仅用于演示的目的,在这里,你需要手动更改“回放速度”,每次你安装了如应用程序:“sp.play(爆炸, 1,1,0,0,1.5f)“这里”1.5f“是播放速率。人们可以很容易地创建一个EditView,或者类似的设置运行时播放速率的值。

在这个应用程序,你只需要点击应用程序的屏幕上以设置的播放速度播放音乐。

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

    } 
}