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.JsonClass
|
||||
|
||||
/**
|
||||
* See https://github.com/matrix-org/matrix-doc/blob/travis/msc/audio-waveform/proposals/3246-audio-waveform.md
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class AudioWaveformInfo(
|
||||
@Json(name = "duration")
|
||||
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")
|
||||
val waveform: List<Int>? = null
|
||||
)
|
||||
|
@ -75,6 +75,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||
private val markdownParser: MarkdownParser,
|
||||
private val textPillsUtils: TextPillsUtils,
|
||||
private val thumbnailExtractor: ThumbnailExtractor,
|
||||
private val waveformSanitizer: WaveFormSanitizer,
|
||||
private val localEchoRepository: LocalEchoRepository,
|
||||
private val permalinkFactory: PermalinkFactory
|
||||
) {
|
||||
@ -302,7 +303,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||
url = attachment.queryUri.toString(),
|
||||
audioWaveformInfo = if (!isVoiceMessage) null else AudioWaveformInfo(
|
||||
duration = attachment.duration?.toInt(),
|
||||
waveform = attachment.waveform
|
||||
waveform = waveformSanitizer.sanitize(attachment.waveform)
|
||||
),
|
||||
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