diff --git a/app/src/main/java/nie/translator/rtranslatordevedition/Global.java b/app/src/main/java/nie/translator/rtranslatordevedition/Global.java index 1186ba7..226ec0b 100644 --- a/app/src/main/java/nie/translator/rtranslatordevedition/Global.java +++ b/app/src/main/java/nie/translator/rtranslatordevedition/Global.java @@ -62,6 +62,8 @@ public class Global extends Application { private ConsumptionsDataManager databaseManager; private AccessToken apiToken; private int micSensitivity = -1; + private int speechTimeout = -1; + private int prevVoiceDuration = -1; private int amplitudeThreshold = Recorder.DEFAULT_AMPLITUDE_THRESHOLD; private Handler mainHandler; private Thread getApiTokenThread; @@ -295,6 +297,38 @@ public void setMicSensitivity(int value) { editor.apply(); } + public int getSpeechTimeout() { + if (speechTimeout == -1) { + final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + speechTimeout = sharedPreferences.getInt("speechTimeout", Recorder.DEFAULT_SPEECH_TIMEOUT_MILLIS); + } + return speechTimeout; + } + + public void setSpeechTimeout(int value) { + speechTimeout = value; + final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putInt("speechTimeout", value); + editor.apply(); + } + + public int getPrevVoiceDuration() { + if (prevVoiceDuration == -1) { + final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + prevVoiceDuration = sharedPreferences.getInt("prevVoiceDuration", Recorder.DEFAULT_PREV_VOICE_DURATION); + } + return prevVoiceDuration; + } + + public void setPrevVoiceDuration(int value) { + prevVoiceDuration = value; + final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putInt("prevVoiceDuration", value); + editor.apply(); + } + private void setAmplitudeThreshold(int micSensitivity) { float amplitudePercentage = 1f - (micSensitivity / 100f); if (amplitudePercentage < 0.5f) { diff --git a/app/src/main/java/nie/translator/rtranslatordevedition/settings/SeekBarPreference.java b/app/src/main/java/nie/translator/rtranslatordevedition/settings/SeekBarPreference.java index f41323b..78470f4 100644 --- a/app/src/main/java/nie/translator/rtranslatordevedition/settings/SeekBarPreference.java +++ b/app/src/main/java/nie/translator/rtranslatordevedition/settings/SeekBarPreference.java @@ -23,15 +23,27 @@ import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.TextView; + import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; + +import java.util.Locale; + import nie.translator.rtranslatordevedition.Global; import nie.translator.rtranslatordevedition.R; +import nie.translator.rtranslatordevedition.voice_translation.cloud_apis.voice.Recorder; public class SeekBarPreference extends Preference { + public static final int MIC_SENSIBILITY_MODE = 0; + public static final int SPEECH_TIMEOUT_MODE = 1; + public static final int PREV_VOICE_DURATION_MODE = 2; + private int mode; + private int defaultValue = 50; private SeekBar seekBar; private TextView value; + private TextView title; + private TextView summary; private ImageButton button; private Global global; @@ -55,13 +67,25 @@ public SeekBarPreference(Context context) { public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); value = (TextView) holder.findViewById(R.id.textViewValue); + title = (TextView) holder.findViewById(R.id.title); + summary = (TextView) holder.findViewById(R.id.summary); seekBar = (SeekBar) holder.findViewById(R.id.seekBar); button = (ImageButton) holder.findViewById(R.id.buttonRestore); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override - public void onProgressChanged(SeekBar seekBar, int seekbarValue, boolean b) { - value.setText(Integer.toString(seekbarValue)); + public void onProgressChanged(SeekBar seekBar, int seekBarValue, boolean b) { + switch (mode) { + case MIC_SENSIBILITY_MODE: + value.setText(String.format(Locale.US, "%d", seekBarValue)); + break; + case SPEECH_TIMEOUT_MODE: + value.setText(String.format(Locale.US, "%.2f s", ((float) seekBarValue + Recorder.MIN_SPEECH_TIMEOUT_MILLIS) / 1000)); + break; + case PREV_VOICE_DURATION_MODE: + value.setText(String.format(Locale.US, "%.2f s", ((float) seekBarValue + Recorder.MIN_PREV_VOICE_DURATION) / 1000)); + break; + } } @Override @@ -71,10 +95,7 @@ public void onStartTrackingTouch(SeekBar seekBar) { @Override public void onStopTrackingTouch(SeekBar seekBar) { - if (global != null) { - // saving the value of the textView value - global.setMicSensitivity(Integer.parseInt(value.getText().toString())); - } + saveValue(); } }); @@ -82,33 +103,102 @@ public void onStopTrackingTouch(SeekBar seekBar) { @Override public void onClick(View view) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - seekBar.setProgress(50, true); + seekBar.setProgress(defaultValue, true); } else { - seekBar.setProgress(50); + seekBar.setProgress(defaultValue); } - // saving the value of the textView value - global.setMicSensitivity(Integer.parseInt(value.getText().toString())); + saveValue(); } }); - if(global!=null){ - setSeekebarValue(); + if (global != null) { //if initialize was run before (and therefore failed to execute the code inside if(seekBar!=null){} ) + initialize(); } } - public void initialize(SettingsActivity activity) { + public void initialize(SettingsActivity activity, int mode) { global = (Global) activity.getApplication(); - if(seekBar!=null){ - setSeekebarValue(); + this.mode = mode; + initialize(); + } + + private void initialize() { + if (seekBar != null) { //if onBindViewHolder was run before (and therefore failed to execute the code inside if(global!=null){} ) + switch (mode) { + case MIC_SENSIBILITY_MODE: + defaultValue = 50; + seekBar.setMax(100); + title.setText(R.string.preference_title_mic_sensitivity); + summary.setText(R.string.preference_description_mic_sensitivity); + break; + + case SPEECH_TIMEOUT_MODE: + defaultValue = Recorder.DEFAULT_SPEECH_TIMEOUT_MILLIS - Recorder.MIN_SPEECH_TIMEOUT_MILLIS; + seekBar.setMax(Recorder.MAX_SPEECH_TIMEOUT_MILLIS - Recorder.MIN_SPEECH_TIMEOUT_MILLIS); //we not use only MAX_SPEECH_TIMEOUT_MILLIS because we can't set the min value, so we set a (MAX - MIN) Max and we add MIN to the value of the SeekBar + title.setText(R.string.preference_title_speech_timeout); + summary.setText(R.string.preference_description_speech_timeout); + break; + + case PREV_VOICE_DURATION_MODE: + defaultValue = Recorder.DEFAULT_PREV_VOICE_DURATION - Recorder.MIN_PREV_VOICE_DURATION; + seekBar.setMax(Recorder.MAX_PREV_VOICE_DURATION - Recorder.MIN_PREV_VOICE_DURATION); + title.setText(R.string.preference_title_prev_voice_duration); + summary.setText(R.string.preference_description_prev_voice_duration); + break; + } + + setSeekBarValue(); } } - public void setSeekebarValue(){ - int value=global.getMicSensitivity(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - seekBar.setProgress(value, true); - } else { - seekBar.setProgress(value); + public void setSeekBarValue() { + switch (mode) { + case MIC_SENSIBILITY_MODE: { + int value = global.getMicSensitivity(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + seekBar.setProgress(value, true); + } else { + seekBar.setProgress(value); + } + } + break; + + case SPEECH_TIMEOUT_MODE: { + int value = global.getSpeechTimeout() - Recorder.MIN_SPEECH_TIMEOUT_MILLIS; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + seekBar.setProgress(value, true); + } else { + seekBar.setProgress(value); + } + } + break; + + case PREV_VOICE_DURATION_MODE: { + int value = global.getPrevVoiceDuration() - Recorder.MIN_PREV_VOICE_DURATION; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + seekBar.setProgress(value, true); + } else { + seekBar.setProgress(value); + } + } + break; + } + } + + private void saveValue() { + if (global != null) { + // saving the value of the textView value + switch (mode) { + case MIC_SENSIBILITY_MODE: + global.setMicSensitivity(Integer.parseInt(value.getText().toString())); + break; + case SPEECH_TIMEOUT_MODE: + global.setSpeechTimeout((int) (Float.parseFloat(value.getText().toString().replace(" s", "")) * 1000)); + break; + case PREV_VOICE_DURATION_MODE: + global.setPrevVoiceDuration((int) (Float.parseFloat(value.getText().toString().replace(" s", "")) * 1000)); + break; + } } } } diff --git a/app/src/main/java/nie/translator/rtranslatordevedition/settings/SettingsFragment.java b/app/src/main/java/nie/translator/rtranslatordevedition/settings/SettingsFragment.java index 67d0a41..ab6b826 100644 --- a/app/src/main/java/nie/translator/rtranslatordevedition/settings/SettingsFragment.java +++ b/app/src/main/java/nie/translator/rtranslatordevedition/settings/SettingsFragment.java @@ -154,8 +154,8 @@ public void onViewHeightMeasured(int height) { });*/ // change microphone sensibility initialization - SeekBarPreference seekBarPreference = (SeekBarPreference) findPreference("micSensibility"); - seekBarPreference.initialize(activity); + SeekBarPreference micSensibilityPreference = (SeekBarPreference) findPreference("micSensibilitySetting"); + micSensibilityPreference.initialize(activity, SeekBarPreference.MIC_SENSIBILITY_MODE); // language support option with low quality tts initialization supportTtsQualityPreference = (SupportTtsQualityPreference) findPreference("languagesQualityLow"); @@ -178,6 +178,14 @@ public boolean onPreferenceClick(Preference preference) { return true; } }); + + // change microphone sensibility initialization + SeekBarPreference speechTimeoutPreference = (SeekBarPreference) findPreference("SpeechTimeoutSetting"); + speechTimeoutPreference.initialize(activity, SeekBarPreference.SPEECH_TIMEOUT_MODE); + + // change microphone sensibility initialization + SeekBarPreference prevVoiceDurationPreference = (SeekBarPreference) findPreference("PrevVoiceDurationSetting"); + prevVoiceDurationPreference.initialize(activity, SeekBarPreference.PREV_VOICE_DURATION_MODE); } @Override diff --git a/app/src/main/java/nie/translator/rtranslatordevedition/voice_translation/cloud_apis/voice/Recorder.java b/app/src/main/java/nie/translator/rtranslatordevedition/voice_translation/cloud_apis/voice/Recorder.java index ed60bf5..5af20e4 100644 --- a/app/src/main/java/nie/translator/rtranslatordevedition/voice_translation/cloud_apis/voice/Recorder.java +++ b/app/src/main/java/nie/translator/rtranslatordevedition/voice_translation/cloud_apis/voice/Recorder.java @@ -47,11 +47,15 @@ public class Recorder { public static final int MAX_AMPLITUDE_THRESHOLD = 15000; public static final int DEFAULT_AMPLITUDE_THRESHOLD = 2000; //original: 1500 public static final int MIN_AMPLITUDE_THRESHOLD = 400; - private static final int SPEECH_TIMEOUT_MILLIS = 750; //original: 2000 - private static final int MAX_SPEECH_LENGTH_MILLIS = 30 * 1000; - private static final double PREV_VOICE_DURATION = 800; + public static final int MAX_SPEECH_TIMEOUT_MILLIS = 5000; + public static final int DEFAULT_SPEECH_TIMEOUT_MILLIS = 800; //original: 2000 + public static final int MIN_SPEECH_TIMEOUT_MILLIS = 100; + public static final int MAX_PREV_VOICE_DURATION = 1500; + public static final int DEFAULT_PREV_VOICE_DURATION = 800; + public static final int MIN_PREV_VOICE_DURATION = 100; + private static final int MAX_SPEECH_LENGTH_MILLIS = 29 * 1000; //original: 30 * 1000 private Timer timer; - private Callback mCallback; + private final Callback mCallback; private AudioRecord mAudioRecord; private Thread mThread; private int mPrevBufferMaxSize; @@ -70,6 +74,8 @@ public class Recorder { public Recorder(Global global, @NonNull Callback callback) { this.global = global; global.getMicSensitivity(); + global.getSpeechTimeout(); + global.getPrevVoiceDuration(); mCallback = callback; mCallback.setRecorder(this); if(!(callback instanceof SimpleCallback)){ @@ -179,7 +185,7 @@ private AudioRecord createAudioRecord() { audioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_RECOGNITION, sampleRate, CHANNEL, ENCODING, sizeInBytes); if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) { mBuffer = new byte[sizeInBytes * 2]; //attention here - mPrevBufferMaxSize = (int) Math.floor((((16f * sampleRate) / 8) * (PREV_VOICE_DURATION /1000)) / mBuffer.length); + mPrevBufferMaxSize = (int) Math.floor((((16f * sampleRate) / 8) * (((double)global.getPrevVoiceDuration()) /1000)) / mBuffer.length); mPrevBuffer = new ArrayDeque<>(); // the prev buffer must contain PREV_VOICE_DURATION seconds of data prior to the buffer return audioRecord; } else { @@ -226,7 +232,7 @@ public void run() { } } else if (mLastVoiceHeardMillis != Long.MAX_VALUE) { mCallback.onVoice(mBuffer, size); - if (now - mLastVoiceHeardMillis > SPEECH_TIMEOUT_MILLIS) { + if (now - mLastVoiceHeardMillis > global.getSpeechTimeout()) { end(); } } diff --git a/app/src/main/res/layout/preference_seekbar.xml b/app/src/main/res/layout/preference_seekbar.xml index 8722047..ef79d94 100644 --- a/app/src/main/res/layout/preference_seekbar.xml +++ b/app/src/main/res/layout/preference_seekbar.xml @@ -81,7 +81,7 @@ android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" android:max="100" - android:progress="50" + android:progress="0" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/textViewValue" app:layout_constraintStart_toEndOf="@+id/buttonRestore" diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 29ba07c..aa33ad3 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -108,13 +108,18 @@ Lingua Output Input + Avanzate Sensibilità microfono Supporto lingue con tts a bassa qualità Lingua personale Sintetizzatore vocale + Timeout fine voce + Durata anticipo voce Seleziona il livello di volume che serve per avviare e mantenere il riconoscimento vocale Permette di supportare anche le lingue che hanno una bassa qualità del sintetizzatore vocale Impostazioni di sistema del tts + Seleziona il tempo che deve trascorrere dopo aver smesso di parlare per inviare il testo trascritto + Seleziona la durata della registrazione precedente a quando si inizia a parlare che verrà inclusa nel riconoscimento vocale \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5e991e7..40cc99e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -112,14 +112,19 @@ Language Output Input + Advanced Microphone sensitivity Support languages ​​with low quality tts Personal language Text to speech + End of voice timeout + Voice anticipation duration Select the volume level you need to start and maintain voice recognition It allow to also supports languages ​​that have a low quality speech synthesizer System settings of tts + Select the time after you stop talking to send the transcribed text + Select the length of the recording before you start speaking that will be included in the voice recognition diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 4ad6044..7dad7b2 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -31,7 +31,7 @@ android:title="@string/preference_header_input" app:iconSpaceReserved="false"> @@ -61,4 +61,16 @@ android:summary="@string/preference_description_tts" app:iconSpaceReserved="false" /> + + + + \ No newline at end of file