2011-10-29 20 views
6

La documentación de Android para SoundPool dice que "la aplicación también puede alterar el tono ajustando la velocidad de reproducción en tiempo real para efectos Doppler o de síntesis". Así que traté de hacer esto, usando el método setRate para variar sin problemas de una nota a otra, pero el resultado es horrible: la variación del sonido es muy desigual. Aquí está el código que probé. Por favor dime si hay una mejor manera.Android audio: cambie el tono

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

cambio '1 + x' a' 1.0f + x' y (también cambiar '' 0.005' a 0.005f' –

+0

Esto no hace ninguna diferencia. – Patrick

+0

¿Cómo estás probando su código. Si está utilizando una dispositivo real, es posible que su dispositivo sea demasiado lento para cambiar dinámicamente la velocidad de reproducción. Si está utilizando el simulador, tal vez el problema sea la tarjeta de sonido de su anfitrión. Cambiar la velocidad de reproducción no es una tarea trivial y puede requerir una interpolación compleja especialmente cuando se ejecuta con tasas de conversión no estándar. – MBober

Respuesta

13

A pesar de que la documentación androides sugiere que se puede utilizar para producir setRate() efectos Doppler, no lo haría depender de una aplicación lo suficientemente rápido o bueno en todos los dispositivos Android.

Los circuitos integrados de audio asequibles requieren una frecuencia de muestreo fija de 44kHz o 48kHz. Por lo tanto, la conversión de velocidad de muestreo (es decir, la modificación de tono) debe realizarse en el software. Debido a que esto incluye el crujido de números de bajo nivel, estoy seguro de que esto es implementado por el fabricante del dispositivo y no por Google. Dada la amplia variedad de fabricantes de dispositivos Android y el hardware a menudo de bajo costo utilizado, sin duda hay muchas implementaciones de conversión de frecuencia de muestreo. Algunos más rápido, otros más lento. Algunos suaves, otros irregulares.

¿Qué sucede al cambiar la tasa de conversión durante la reproducción? Si el algoritmo no hace coincidir las piezas exactamente juntas, puede haber una pequeña grieta en la reproducción de audio. Cambia la tasa de conversión cada 10 milisegundos. Si hay una grieta cada 10 ms, eso corresponde a una frecuencia de 100 Hz, que es un tono en sí mismo. Es probable que esto sea lo que escuchas como "harapiento".

En general, no creo que sea posible emular instrumentos musicales en tiempo real en una amplia gama de dispositivos Android que usan Android API de alto nivel. Sin embargo, una aplicación nativa puede ser lo suficientemente rápida.

0

Después de probar todo, decidí usar SoundPool para cambiar el tono, una velocidad de reproducción de 2.0 hace que el sonido se reproduzca a una frecuencia doble al original, y una velocidad de reproducción de 0.5 hace que se reproduzca a la mitad frecuencia original. El rango de velocidad de reproducción es de 0.5 a 2.0. Pero funcionó con frecuencia más baja y más alta que 0.5 y 2.0.

Estoy publicar mi código de trabajo,

pero como es sólo para fines de demostración, aquí tienes que cambiar manualmente la "tasa de reproducción", cada vez que se instala la aplicación para, por ejemplo: "sp.play (explosión, 1,1,0,0,1.5f) "here" 1.5f "es la velocidad de reproducción. Uno puede crear fácilmente un EditView, o algo similar para establecer el valor de la velocidad de reproducción en tiempo de ejecución.

En esta aplicación, solo necesita tocar en la pantalla de la aplicación para reproducir la música a la velocidad de reproducción establecida.

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

    } 
}