Предпочтительный способ присоединения AudioEffect к глобальному миксу?

В Android AudioEffect API все встроенные эффекты, такие как эквалайзер, сопровождаются предупреждением.

«ПРИМЕЧАНИЕ: присоединение эквалайзера к общему миксу аудиовыхода с использованием сеанса 0 не рекомендуется».

Если это устарело, то чем заменить API? Моя цель состоит в том, чтобы добавить эффект к общему выходному миксу...


person yano    schedule 22.02.2012    source источник


Ответы (3)


Да, он устарел из-за побочных эффектов.

На веб-сайте разработчиков Android указано, что второй параметр класса Equalizer должен быть:

Общесистемный уникальный идентификатор аудиосессии. Эквалайзер будет подключен к MediaPlayer или AudioTrack в том же аудиосеансе.

Вместо этого вы должны использовать это:

MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource( _your_data_source_ );
Equalizer equalizer = new Equalizer(0, mediaPlayer.getAudioSessionId());
equalizer.setEnabled(true);
/* Do your stuff ... */
mediaPlayer.start();
person Halim Qarroum    schedule 05.04.2013
comment
Как упоминалось в одном из комментариев к вашей ссылке, это не обходной путь, если вы хотите применить эквалайзер или другой эффект к существующему потоку или ко всем потокам. - person yano; 06.04.2013
comment
На данный момент вы потенциально все еще можете использовать глобальный аудиосеанс с файлом Equalizer. Замены нет, устаревание не всегда сопровождается заменой. Они просто поняли, что это не работает должным образом, и решили сохранить поддержку до следующих выпусков Android. Обходной путь в вашем случае — подключить эквалайзер к каждому экземпляру MediaPlayer в ваших приложениях. Если нет, рискните оставить Equalizer подключенным к глобальному аудиосеансу, зная, что он точно не будет работать в следующих выпусках. - person Halim Qarroum; 06.04.2013
comment
Привет Халим, Как прикрепить эквалайзер к каждому экземпляру MediaPlayer? Пожалуйста, поделитесь дополнительной информацией об этом. Также какова альтернатива глобальному приложению эффекта в ICS? - person JRC; 24.07.2013

Нет альтернативы присоединению AudioEffect к глобальному выходу. Вместо этого вам следует зарегистрировать широковещательный приемник, который получает все аудиосессии, чтобы вы могли применять к нему звуковые эффекты. Пример можно найти здесь . Намерение, содержащее идентификатор сеанса, получено в этом BroadcastReceiver. Помните, что это работает, только если вы зарегистрировали приемник в манифесте. В качестве альтернативы вы можете программно зарегистрировать приемник в своей службе onCreate():

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

где mAudioSessionReceiver выглядит примерно так:

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

Затем вы можете получить намерение в 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
}`

Наконец, не забудьте отменить регистрацию получателя в onDestroy():

unregisterReceiver(mAudioSessionReceiver)`
person Thomas W.    schedule 24.11.2019

Согласно Android, вы можете использовать ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION для получения идентификатор воспроизводимой аудиосессии:

Намерение сообщить приложению или службе управления эффектами, что новый аудиосеанс открыт и требует применения аудиоэффектов.

Я попытался добавить константу в манифест, но это не сработало:

<receiver android:name=".receivers.AudioSessionReceiver">
        <intent-filter>
            <action android:name="android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION"/>
        </intent-filter>
</receiver>

Если вы выясните, как использовать константу, намерение будет содержать идентификатор аудиосессии, который вы можете использовать для применения желаемых настроек эквалайзера. (Если вы нашли обходной путь за все эти годы, не могли бы вы поделиться?)

person Dropin' Science    schedule 03.10.2019
comment
Это работает только со Spotify, вы знали об этом? - person Rishabh Sagar; 02.03.2021