mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-01-31 03:17:13 +01:00
Follow the spec regarding waveform content
This commit is contained in:
parent
95bb796bad
commit
6a0ea11e7a
@ -19,11 +19,18 @@ package org.matrix.android.sdk.api.session.room.model.message
|
|||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://github.com/matrix-org/matrix-doc/blob/travis/msc/audio-waveform/proposals/3246-audio-waveform.md
|
||||||
|
*/
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class AudioWaveformInfo(
|
data class AudioWaveformInfo(
|
||||||
@Json(name = "duration")
|
@Json(name = "duration")
|
||||||
val duration: Int? = null,
|
val duration: Int? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array should have no less than 30 elements and no more than 120.
|
||||||
|
* List of integers between zero and 1024, inclusive.
|
||||||
|
*/
|
||||||
@Json(name = "waveform")
|
@Json(name = "waveform")
|
||||||
val waveform: List<Int>? = null
|
val waveform: List<Int>? = null
|
||||||
)
|
)
|
||||||
|
@ -75,6 +75,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||||||
private val markdownParser: MarkdownParser,
|
private val markdownParser: MarkdownParser,
|
||||||
private val textPillsUtils: TextPillsUtils,
|
private val textPillsUtils: TextPillsUtils,
|
||||||
private val thumbnailExtractor: ThumbnailExtractor,
|
private val thumbnailExtractor: ThumbnailExtractor,
|
||||||
|
private val waveformSanitizer: WaveFormSanitizer,
|
||||||
private val localEchoRepository: LocalEchoRepository,
|
private val localEchoRepository: LocalEchoRepository,
|
||||||
private val permalinkFactory: PermalinkFactory
|
private val permalinkFactory: PermalinkFactory
|
||||||
) {
|
) {
|
||||||
@ -302,7 +303,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||||||
url = attachment.queryUri.toString(),
|
url = attachment.queryUri.toString(),
|
||||||
audioWaveformInfo = if (!isVoiceMessage) null else AudioWaveformInfo(
|
audioWaveformInfo = if (!isVoiceMessage) null else AudioWaveformInfo(
|
||||||
duration = attachment.duration?.toInt(),
|
duration = attachment.duration?.toInt(),
|
||||||
waveform = attachment.waveform
|
waveform = waveformSanitizer.sanitize(attachment.waveform)
|
||||||
),
|
),
|
||||||
voiceMessageIndicator = if (!isVoiceMessage) null else emptyMap()
|
voiceMessageIndicator = if (!isVoiceMessage) null else emptyMap()
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.internal.session.room.send
|
||||||
|
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.ceil
|
||||||
|
|
||||||
|
internal class WaveFormSanitizer @Inject constructor() {
|
||||||
|
private companion object {
|
||||||
|
const val MIN_NUMBER_OF_VALUES = 30
|
||||||
|
const val MAX_NUMBER_OF_VALUES = 120
|
||||||
|
|
||||||
|
const val MAX_VALUE = 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array should have no less than 30 elements and no more than 120.
|
||||||
|
* List of integers between zero and 1024, inclusive.
|
||||||
|
*/
|
||||||
|
fun sanitize(waveForm: List<Int>?): List<Int>? {
|
||||||
|
if (waveForm.isNullOrEmpty()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit the number of items
|
||||||
|
val result = mutableListOf<Int>()
|
||||||
|
if (waveForm.size < MIN_NUMBER_OF_VALUES) {
|
||||||
|
// Repeat the same value to have at least 30 items
|
||||||
|
val repeatTimes = ceil(MIN_NUMBER_OF_VALUES / waveForm.size.toDouble()).toInt()
|
||||||
|
waveForm.map { value ->
|
||||||
|
repeat(repeatTimes) {
|
||||||
|
result.add(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (waveForm.size > MAX_NUMBER_OF_VALUES) {
|
||||||
|
val keepOneOf = ceil(waveForm.size.toDouble() / MAX_NUMBER_OF_VALUES).toInt()
|
||||||
|
waveForm.mapIndexed { idx, value ->
|
||||||
|
if (idx % keepOneOf == 0) {
|
||||||
|
result.add(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.addAll(waveForm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK, ensure all items are positive
|
||||||
|
val limited = result.map {
|
||||||
|
abs(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure max is not above MAX_VALUE
|
||||||
|
val max = limited.maxOrNull() ?: MAX_VALUE
|
||||||
|
|
||||||
|
val final = if (max > MAX_VALUE) {
|
||||||
|
// Reduce the range
|
||||||
|
limited.map {
|
||||||
|
it * MAX_VALUE / max
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
limited
|
||||||
|
}
|
||||||
|
|
||||||
|
return final
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.internal.session.room.send
|
||||||
|
|
||||||
|
import org.amshove.kluent.shouldBe
|
||||||
|
import org.amshove.kluent.shouldBeInRange
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class WaveFormSanitizerTest {
|
||||||
|
|
||||||
|
private val waveFormSanitizer = WaveFormSanitizer()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitizeNull() {
|
||||||
|
waveFormSanitizer.sanitize(null) shouldBe null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitizeEmpty() {
|
||||||
|
waveFormSanitizer.sanitize(emptyList()) shouldBe null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitizeSingleton() {
|
||||||
|
val result = waveFormSanitizer.sanitize(listOf(1))!!
|
||||||
|
result.size shouldBe 30
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitize29() {
|
||||||
|
val list = generateSequence { 1 }.take(29).toList()
|
||||||
|
val result = waveFormSanitizer.sanitize(list)!!
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitize30() {
|
||||||
|
val list = generateSequence { 1 }.take(30).toList()
|
||||||
|
val result = waveFormSanitizer.sanitize(list)!!
|
||||||
|
result.size shouldBe 30
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitize31() {
|
||||||
|
val list = generateSequence { 1 }.take(31).toList()
|
||||||
|
val result = waveFormSanitizer.sanitize(list)!!
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitize119() {
|
||||||
|
val list = generateSequence { 1 }.take(119).toList()
|
||||||
|
val result = waveFormSanitizer.sanitize(list)!!
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitize120() {
|
||||||
|
val list = generateSequence { 1 }.take(120).toList()
|
||||||
|
val result = waveFormSanitizer.sanitize(list)!!
|
||||||
|
result.size shouldBe 120
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitize121() {
|
||||||
|
val list = generateSequence { 1 }.take(121).toList()
|
||||||
|
val result = waveFormSanitizer.sanitize(list)!!
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitize1024() {
|
||||||
|
val list = generateSequence { 1 }.take(1024).toList()
|
||||||
|
val result = waveFormSanitizer.sanitize(list)!!
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitizeNegative() {
|
||||||
|
val list = generateSequence { -1 }.take(30).toList()
|
||||||
|
val result = waveFormSanitizer.sanitize(list)!!
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitizeMaxValue() {
|
||||||
|
val list = generateSequence { 1025 }.take(30).toList()
|
||||||
|
val result = waveFormSanitizer.sanitize(list)!!
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sanitizeNegativeMaxValue() {
|
||||||
|
val list = generateSequence { -1025 }.take(30).toList()
|
||||||
|
val result = waveFormSanitizer.sanitize(list)!!
|
||||||
|
checkResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkResult(result: List<Int>) {
|
||||||
|
result.forEach {
|
||||||
|
it shouldBeInRange 0..1024
|
||||||
|
}
|
||||||
|
|
||||||
|
result.size shouldBeInRange 30..120
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user