2011-10-29 2 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.005f' –

+0

이 차이가 없습니다에'0.005'을 변경'에. – Patrick

+0

어떻게 당신의 코드를 테스트하고 있습니다. 당신은을 사용하는 경우 실제 장치에서 재생 속도를 동적으로 변경하기에는 장치 속도가 너무 느릴 수 있습니다. 시뮬레이터를 사용하는 경우 호스트의 사운드 카드가 문제 일 수 있습니다. 재생 속도를 변경하는 것은 간단한 작업이 아니며 복잡한 보간이 필요할 수 있습니다 특히 비표준 변환율로 실행할 때 – MBober

답변

13

심지어 안드로이드 문서는, 도플러 효과를 만들어 setRate()를 사용하여 내가 모든 안드로이드 장치에 빠르게 또는 충분히 좋은 구현에 의존하지 않을 것을 제안하지만.

저렴한 오디오 IC는 44kHz 또는 48kHz의 고정 샘플 속도가 필요합니다. 따라서 샘플 레이트 변환 (즉, 피치 수정)은 소프트웨어에서 수행되어야합니다. 여기에는 하위 수준의 수치 계산 기능이 포함되어 있으므로 Google이 아닌 기기 제조업체가이를 구현했다고 확신합니다. 다양한 안드로이드 장치 제조업체와 종종 저가의 하드웨어를 사용하기 때문에 확실히 많은 샘플 속도 변환 구현이 가능합니다. 일부는 더 빠르며, 좀 더 느립니다. 어떤 것은 매끄럽고, 어떤 것은 거친.

재생 중 변환 속도를 변경하면 어떻게됩니까? 알고리즘이 정확하게 일치하지 않으면 오디오 재생에 짧은 균열이있을 수 있습니다. 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); 
     } 

    } 
}