diff --git a/src/components/messages/AudioPlayer.vue b/src/components/messages/AudioPlayer.vue index cf7472c..f0194b3 100644 --- a/src/components/messages/AudioPlayer.vue +++ b/src/components/messages/AudioPlayer.vue @@ -6,15 +6,22 @@
{{ currentTime }} / {{ totalTime }}
+
+
+ +
+
+ + \ No newline at end of file diff --git a/src/plugins/utils.js b/src/plugins/utils.js index 56368b3..bdc8646 100644 --- a/src/plugins/utils.js +++ b/src/plugins/utils.js @@ -424,6 +424,9 @@ class Util { promise .then((response) => { messageContent.url = response.content_uri; + return (msgtype == 'm.audio' ? this.generateWaveform(fileContents, messageContent) : true); + }) + .then(() => { return this.sendMessage(matrixClient, roomId, "m.room.message", messageContent) }) .then(result => { @@ -478,6 +481,9 @@ class Util { return reject(response.error); } encryptedFile.url = response.content_uri; + return (msgtype == 'm.audio' ? this.generateWaveform(fileContents, messageContent) : true); + }) + .then(() => { return this.sendMessage(matrixClient, roomId, "m.room.message", messageContent) }) .then(result => { @@ -495,6 +501,51 @@ class Util { return uploadPromise; } + generateWaveform(data, messageContent) { + if (!(window.AudioContext || window.webkitAudioContext)) { + return; // No support + } + const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); + if (audioCtx) { + return audioCtx.decodeAudioData(data) + .then((audioBuffer) => { + const rawData = audioBuffer.getChannelData(0); // TODO - currently using only 1 channel + const samples = 1000; // Number of samples + const blockSize = Math.floor(rawData.length / samples); + let filteredData = []; + for (let i = 0; i < samples; i++) { + let blockStart = blockSize * i; // the location of the first sample in the block + let sum = 0; + for (let j = 0; j < blockSize; j++) { + sum = sum + Math.abs(rawData[blockStart + j]) // find the sum of all the samples in the block + } + filteredData.push(sum / blockSize); // divide the sum by the block size to get the average + } + + // Normalize + const multiplier = Math.pow(Math.max(...filteredData), -1); + filteredData = filteredData.map(n => n * multiplier); + + // Integerize + filteredData = filteredData.map(n => parseInt((n * 255).toFixed())); + + + // Generate SVG of waveform + let svg = ``; + svg += ``; + svg += ""; + + messageContent.format = "org.matrix.custom.html"; + messageContent.formatted_body = svg; + }) + } + } + /** * Return what "mode" to use for the given room. *