TTS не зависит от громкости, установленной AudioManager - PullRequest
0 голосов
/ 01 октября 2018

У меня проблема с реализацией приложения TTS (Text To Speech).По сути, я пытаюсь переопределить текущую громкость максимальной громкостью, когда я запускаю свой метод преобразования текста в речь.Я вижу изменения в регуляторе громкости на телефоне, но, похоже, он не влияет на громкость TTS, так как громкость TTS остается прежней.Я не могу понять точную проблему.

3 метода, которые я вызываю в последовательности

setMaxVolume();
activateTTS(myString);
setDefaultVolume();

setMaxVolume

private void setMaxVolume(){
    audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
}

активировать TTS

private void activateTTS(String myString) {

    if(androidAPILevel < 21){
        HashMap<String, String> params = new HashMap<>();
        params.put(TextToSpeech.Engine.KEY_PARAM_VOLUME, "1");
        textToSpeech.speak(myString, TextToSpeech.QUEUE_FLUSH, params);
    } else{
        Bundle params = new Bundle();
        params.putFloat(TextToSpeech.Engine.KEY_PARAM_VOLUME, 1f);
        textToSpeech.speak(myString, TextToSpeech.QUEUE_FLUSH, params, null);
    }

}

setDefaultVolume

private void setDefaultVolume(){
    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume, 0);
}

Цель состоит в том, чтобы предоставить пользователю регулятор громкости и не разрешатьна услугу TTS влияет громкость телефона.

Дополнительные функции, помогающие решить проблему:

private TextToSpeech textToSpeech;
private int androidAPILevel = Build.VERSION.SDK_INT;
AudioManager audioManager;
int currentVolume;

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    textToSpeech = new TextToSpeech(this,
            this
    );

    textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
        @Override
        public void onStart(String s) {

        }

        @Override
        public void onDone(String s) {
            if (!getUserPreference().getTest()) {
                Toast.makeText(TimeWhisperService.this, "TTS Finished", Toast.LENGTH_SHORT).show();
                setDefaultVolume();
            }
        }

        @Override
        public void onError(String s) {

        }
    });

    Log.v(TAG, "oncreate_service");
    super.onCreate();
}

@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    if (textToSpeech != null) {
        textToSpeech.stop();
        textToSpeech.shutdown();
    }
    super.onDestroy();
}

@Override
public void onStart(Intent intent, int startId) {
    textToSpeech.setSpeechRate(Float.parseFloat(getUserPreference().getSpeed() + "f"));
    textToSpeech.setPitch(Float.parseFloat(getUserPreference().getPitch() + "f"));


    if(getUserPreference().getTest()) {
        activateTTS(getMyString());
    }
    else{
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                setMaxVolume();
                activateTTS(getMyString());
                //setDefaultVolume();
            }
        }, 0, getUserPreference().getTimer() * 10000);
        Log.v(TAG, "onstart_service");
    }
    super.onStart(intent, startId);
}

@Override
public void onInit(int status) {
    Log.v(TAG, "oninit");
    if (status == TextToSpeech.SUCCESS) {
        int result = textToSpeech.setLanguage(Locale.UK);
        if (result == TextToSpeech.LANG_MISSING_DATA ||
            result == TextToSpeech.LANG_NOT_SUPPORTED) {
            Log.v(TAG, "Language is not available.");
        } else {
            //textToSpeech.setOnUtteranceCompletedListener(this);
            activateTTS(getMyString());
        }
    } else {
        Log.v(TAG, "Could not initialize TextToSpeech.");
    }
}

1 Ответ

0 голосов
/ 05 октября 2018

Проблема в том, что вы «вызываете последовательно» ваши три метода, но в действительности происходит то, что третий метод вызывается, возвращая системный объем обратно в нормальное состояние ... до того, как TTS даже начнет говорить.

Причина в том, что согласно документации метод speak () является асинхронным.

Итак ... способ решить эту проблему - создать UtteranceProgressListener ичтобы переместить метод setDefaultVolume () в его метод onDone ().

Примечание: для того, чтобы любой из обратных вызовов UtteranceProgressListener был вызван, utteranceID не может быть нулевым ... так что это также изменяется:

public class MainActivity extends AppCompatActivity {

    int androidAPILevel = android.os.Build.VERSION.SDK_INT;
    TextToSpeech textToSpeech;
    AudioManager audioManager;
    int currentVolume;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textToSpeech = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int i) {
                start();
            }
        });

        textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
            @Override
            public void onStart(String s) {
            }
            @Override
            public void onDone(String s) {
                Log.i("XXX", "onDone() called.");
                setDefaultVolume(); // sets volume back to normal *after* speech is done.
            }
            @Override
            public void onError(String s) {
                Log.i("XXX", "onError() called.");
                setDefaultVolume(); // sets volume back to normal *after* speech is done.
            }
        });
    }

    private void start() {
        setMaxVolume();
        activateTTS("hello! hello! hello! hello! hello! hello!");
    }

    private void activateTTS(String myString) {

        if(androidAPILevel < 21){
            HashMap<String, String> params = new HashMap<>();
            params.put(TextToSpeech.Engine.KEY_PARAM_VOLUME, "1");
            params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "thisNeedsToBeSet");
            textToSpeech.speak(myString, TextToSpeech.QUEUE_FLUSH, params);
        } else{
            Bundle params = new Bundle();
            params.putFloat(TextToSpeech.Engine.KEY_PARAM_VOLUME, 1f);
            textToSpeech.speak(myString, TextToSpeech.QUEUE_FLUSH, params, "thisNeedsToBeSet");
        }

    }

    private void setMaxVolume(){
        audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
    }

    private void setDefaultVolume(){
        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume, 0);
    }

}

РЕДАКТИРОВАТЬ: Хорошая идея - реализовать желаемое поведение в ОБА обратных вызовах onError () и onDone ().Один или другой из них всегда называется, насколько я понимаю.Таким образом, в случае ошибки ваш объем не застрянет в верхнем положении.

...