From cb72fb0d5a3d44e64e6664b6f0006bffed9ad80f Mon Sep 17 00:00:00 2001 From: Eoin Mcloughlin Date: Sun, 28 Aug 2022 10:01:55 +0100 Subject: [PATCH] Use sound generator to calculate real lesson duration Approximation of farnsworth WPM wasn't accurate enough. This can go a second or two over, but that feels alright. --- .../java/es/eoinrul/ecwt/DitDahGenerator.kt | 19 +++++++++++++++++-- .../java/es/eoinrul/ecwt/TrainingActivity.kt | 10 ++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/es/eoinrul/ecwt/DitDahGenerator.kt b/app/src/main/java/es/eoinrul/ecwt/DitDahGenerator.kt index 2249698..3baecbc 100644 --- a/app/src/main/java/es/eoinrul/ecwt/DitDahGenerator.kt +++ b/app/src/main/java/es/eoinrul/ecwt/DitDahGenerator.kt @@ -414,7 +414,7 @@ class DitDahSoundStream { // Apply an attack and release envelope to each of the samples to avoid a pop // in the audio that's generated. Empirically, 8ms seems to eliminate it while // still being fast enough that it works on the fastest WPM setting: - var attackReleaseDuration = 0.008f; + val attackReleaseDuration = 0.008f; val attackReleaseTimeInSamples = (attackReleaseDuration * mAudioSampleRate).toInt(); for(i in 0 until attackReleaseTimeInSamples) { val frac = i.toFloat() / attackReleaseTimeInSamples.toFloat(); @@ -436,6 +436,21 @@ class DitDahSoundStream { } } + // Returns the duration of the sequence, in seconds + fun durationOf(symbols : List): Float { + var numSamples = 0 + for(sym in symbols) { + numSamples += when(sym) { + SoundTypes.DIT -> mDitSound + SoundTypes.DAH -> mDahSound + SoundTypes.LETTER_SPACE -> mCharacterSpacingSound + SoundTypes.WORD_SPACE -> mWordSpacingSound + }.size + } + + return numSamples.toFloat() / mAudioSampleRate.toFloat(); + } + fun quit() { mShouldQuit = true; @@ -539,4 +554,4 @@ class DitDahSoundStream { .setTransferMode(AudioTrack.MODE_STREAM) .setBufferSizeInBytes(mAudioSampleRate) .build(); -} \ No newline at end of file +} diff --git a/app/src/main/java/es/eoinrul/ecwt/TrainingActivity.kt b/app/src/main/java/es/eoinrul/ecwt/TrainingActivity.kt index 6026978..f59f08a 100644 --- a/app/src/main/java/es/eoinrul/ecwt/TrainingActivity.kt +++ b/app/src/main/java/es/eoinrul/ecwt/TrainingActivity.kt @@ -79,8 +79,6 @@ class TrainingActivity : AppCompatActivity(), if(mLessonStarted) return - val generatorSettings = DitDahGeneratorSettings() - val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) val lessonLengthInMinutes = sharedPreferences.getInt(getString(R.string.setting_koch_lesson_length_key), 1) @@ -93,12 +91,12 @@ class TrainingActivity : AppCompatActivity(), var sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this) val shortLessonDebug = sharedPrefs.getBoolean("debug_override_lesson_length", false) - val numberOfWords = if(shortLessonDebug) { + val lessonDurationS = if(shortLessonDebug) { // This makes it much faster to test functionality, if enabled in preferences - 2 + 15 } else { // This is only an approximation - generatorSettings.farnsworthWordsPerMinute * lessonLengthInMinutes + lessonLengthInMinutes * 60 } // If selected in preferences, modify the alphabet used for the lesson so that @@ -117,7 +115,7 @@ class TrainingActivity : AppCompatActivity(), // Create the actual text used for the lesson var lessonText = String() var rng = Random.Default - for(i in 0 until numberOfWords) { + while(mSoundPlayer!!.durationOf(StringToSoundSequence(lessonText)) < lessonDurationS) { val thisWordSize = rng.nextInt(minWordSize, maxWordSize + 1) for(c in 0 until thisWordSize) { val randomLetterIndex = rng.nextInt(0, lessonAlphabet.length)