Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preferred way to attach AudioEffect to global mix?

In Android, AudioEffect API, all of the builtin effects such as Equalizer come with a warning

"NOTE: attaching an Equalizer to the global audio output mix by use of session 0 is deprecated. "

If this is deprecated, then what is the replacement API? My goal is to attach an effect to the global output mix...

like image 382
yano Avatar asked Feb 22 '12 23:02

yano


2 Answers

Yes it is deprecated, because of side-effects isues.

The Android Developers website states that the second parameter of the Equalizer class should be :

A system wide unique audio session identifier. The Equalizer will be attached to the MediaPlayer or AudioTrack in the same audio session.

You should use this instead :

MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource( _your_data_source_ );
Equalizer equalizer = new Equalizer(0, mediaPlayer.getAudioSessionId());
equalizer.setEnabled(true);
/* Do your stuff ... */
mediaPlayer.start();
like image 64
Halim Qarroum Avatar answered Sep 21 '22 13:09

Halim Qarroum


There is no alternative to attach an AudioEffect to the global output. What you should do instead is register a broadcast receiver that receives all audio sessions, so you can apply audio effects to that. An example can be found here. The intent containing the session ID is obtained in this BroadcastReceiver. Remember that this only works if you registered the receiver in the manifest. Alternatively you could register a receiver programmatically like this in your service onCreate():

IntentFilter()
    .apply { addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) }
    .apply { addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION) }
    .run { registerReceiver(mAudioSessionReceiver, this) } `

where mAudioSessionReceiver looks something like this:

private val mAudioSessionReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent == null || context == null) {
            return
        }

        val sessionStates = arrayOf(
            AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION,
            AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION
        )
        if (sessionStates.contains(intent.action)) {
            val service = Intent(context, WaveletService::class.java)
            val sessionID = intent.getIntExtra(AudioEffect.EXTRA_AUDIO_SESSION, AudioEffect.ERROR)
            service
                .apply { action = intent.action }
                .apply { putExtra(AudioEffect.EXTRA_AUDIO_SESSION, sessionID) }
            context.startService(service)
        }
    }
}`

Then, you can obtain the intent in onStartCommand:

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    if (intent == null)
        return START_STICKY

    val sessionID = intent.getIntExtra(AudioEffect.EXTRA_AUDIO_SESSION, AudioEffect.ERROR)

    when (intent.action) {
        AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION -> {
            // create new instance of the AudioEffect using the sessionID
        }
        AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION -> {
            // Release instance of the AudioEffect connected to this sessionID 
        }
    }

    return START_REDELIVER_INTENT
}`

Lastly, don't forget to unregister the receiver in onDestroy():

unregisterReceiver(mAudioSessionReceiver)`
like image 25
Thomas W. Avatar answered Sep 21 '22 13:09

Thomas W.