diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/AudioWaveformInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/AudioWaveformInfo.kt
index 0e2f0f880c..d576f1057a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/AudioWaveformInfo.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/AudioWaveformInfo.kt
@@ -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
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt
index fb56587ac1..c610326a94 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt
@@ -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()
         )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/WaveFormSanitizer.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/WaveFormSanitizer.kt
new file mode 100644
index 0000000000..2bc5cb2475
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/WaveFormSanitizer.kt
@@ -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
+    }
+}
diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/send/WaveFormSanitizerTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/send/WaveFormSanitizerTest.kt
new file mode 100644
index 0000000000..23c8aeb76b
--- /dev/null
+++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/send/WaveFormSanitizerTest.kt
@@ -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
+    }
+}