2012-05-05 4 views
3

J'ai une classe qui utilise AudioTrack pour générer un son par fréquence spécifique. Tout fonctionne bien, mais maintenant je veux le personnaliser afin que je puisse jouer le son uniquement sur le côté droit du casque, ou seulement sur le côté gauche du casque. (oreille droite ou gauche)Android - AudioTrack setStereoVolume() ne fonctionne pas

Donc j'ai trouvé que AudioTrack a une telle méthode: setStereoVolume(), cependant, quand je le configure, par exemple comme ceci: audioTrack.setStereoVolume(1.0f, 0.0f), je m'attends à ce que seulement mon côté gauche des écouteurs sonnent et le côté droit devrait être muet, mais il n'a pas d'effet. Je peux entendre le son au même volume sur les deux côtés droit et gauche du casque.

Je vérifie la valeur de retour de setStreamVolume() et c'est 0, ce qui est égal à SUCCESS, mais je n'entends toujours pas la différence. Savez-vous pourquoi cela ne fonctionne pas, ou d'une manière différente comment je peux spécifier pour jouer le son seulement sur le côté gauche ou droit du casque?

Voici le code qui génère le son:

public class SoundGenerator extends AsyncTask<Float, Void, Void> { 
    final int SAMPLE_RATE = 11025; 
    boolean playing=false; 

    @Override 
    protected Void doInBackground(Float... params) { 

     float frequency=params[0]; 

     int minSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, 
       AudioFormat.CHANNEL_CONFIGURATION_STEREO, 
       AudioFormat.ENCODING_PCM_16BIT); 

     AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 
       SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_STEREO, 
       AudioFormat.ENCODING_PCM_16BIT, minSize, 
       AudioTrack.MODE_STREAM); 

     short[] buffer = new short[minSize]; 

     float angular_frequency = (float) (2 * Math.PI) * frequency/SAMPLE_RATE; 
     float angle = 0; 

     audioTrack.play(); 
     int stereo=audioTrack.setStereoVolume(1.0f, 0.0f); 

       Log.d("GREC", "Stereo vol: "+stereo); 


     while (playing) { 

      for (int i = 0; i < buffer.length; i++) { 
       buffer[i] = (short) (Short.MAX_VALUE * ((float) Math.sin(angle))); 
       angle += angular_frequency; 
      } 
      audioTrack.write(buffer, 0, buffer.length); 
     } 
     Log.d(Globals.TAG, "Stopping the tone generator..."); 
     audioTrack.stop(); 
     audioTrack.release(); 

     return null; 
    } 

    public void keepPlaying(boolean flag){ 
     playing=flag; 
    } 
} 
+1

J'ai trouvé le problème moi-même. Il semble que cela ne fonctionne pas sur l'émulateur, mais a bien fonctionné sur un périphérique réel. – VCODE

Répondre

0

J'ai remarqué même problème. setStereoVolume travaillait sur l'émulateur Android 4.3 mais ne fonctionnait pas sur l'appareil Android 4.0.3.

J'ai étudié Android 4.0.3 AudioTrack.java source et trouvé que si j'appelle setStereoVolume avant que l'écriture est appelée pour AudioTrack cela ne fonctionne pas en retournant ERROR_INVALID_OPERATION en raison d'une valeur mState invalide.

public int setStereoVolume(float leftVolume, float rightVolume) { 
     if (mState != STATE_INITIALIZED) { 
      return ERROR_INVALID_OPERATION; 
     } 
... 
} 

Alors j'ai changé séquence d'appels et a ajouté setStereoVolume après l'appel audioTrack.write et il a commencé à travailler très bien. On dirait que la méthode d'écriture modifie la valeur mState

public int write(byte[] audioData,int offsetInBytes, int sizeInBytes) { 
    if ((mDataLoadMode == MODE_STATIC) 
      && (mState == STATE_NO_STATIC_DATA) 
      && (sizeInBytes > 0)) { 
      mState = STATE_INITIALIZED; 
    } 
    ... 
}