diff --git a/README.md b/README.md index 63d686c..11724d4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -

- -

+# Amplituda ![GitHub release (latest by date)](https://img.shields.io/github/v/release/lincollincol/Amplituda) ![GitHub](https://img.shields.io/github/license/lincollincol/Amplituda) @@ -9,50 +7,138 @@ ![GitHub stars](https://img.shields.io/github/stars/lincollincol/Amplituda?style=social) ![GitHub forks](https://img.shields.io/github/forks/lincollincol/Amplituda?style=social) +## What is Amplituda? +Amplituda - an android library based on FFMPEG which process audio file and provide an array of samples. Based on the processed data, you can easily draw custom waveform using the value of the processed data array as the height of the single column. +Average processing time is equal to 1 second for audio with duration **3 min 20 seconds** and **1 hour** audio will be processed in approximately 20 seconds. -### This library using ffmpeg source. If you want to calculate amplitudes from and draw waveform - use Amplituda library -#### Used pre-build libraries: libavutil.so, libavcodec.so, libavformat.so, libavresampe.so +You can also use WaveformSeekBar library which is fully compatible with Amplituda +

+ ⠀ ⠀ + +

+ ⠀ ⠀ + +

+ ⠀ ⠀ +

+ +## How to use Amplituda? +### • Process audio +``` java +Amplituda amplituda = new Amplituda(context); +// From String path +amplituda.fromFile("/storage/emulated/0/Music/Linc - Amplituda.mp3"); +// From File +amplituda.fromFile(new File("/storage/emulated/0/Music/Linc - Amplituda.mp3")); +// From res/raw file +amplituda.fromFile(R.raw.amplituda); + +/** Amplituda will process your file immediately after fromFile() call */ +``` -# Download -## Gradle -``` groovy -allprojects { - repositories { - maven { url 'https://jitpack.io' } - } -} -``` -``` groovy -dependencies { - implementation 'com.github.lincollincol:Amplituda:1.7' -} -``` +### • Handle result +``` java +// Get result as list +amplituda.amplitudesAsList(amplitudes -> { + System.out.println(Arrays.toString(amplitudes.toArray())); + // Output: 0 0 0 0 0 5 3 6 . . . 6 4 7 1 0 0 0 +}) + +// Get result as list only for second `1` +.amplitudesForSecond(1, amplitudes -> { + System.out.println(Arrays.toString(amplitudes.toArray())); + // Output: 0 0 5 . . . 6 4 0 +}) + +// Get result as json format String +.amplitudesAsJson(json -> { + System.out.println(json); + // Output: [0, 0, 0, 0, 0, 5, 3, 6, . . . , 6, 4, 7, 1, 0, 0, 0] +}) + +// Get result as single line sequence format String (horizontal String) +.amplitudesAsSequence(Amplituda.SINGLE_LINE_SEQUENCE_FORMAT, horizontalSequenceString -> { + System.out.println(horizontalSequenceString); + // Output: 0 0 0 0 0 5 3 6 . . . 6 4 7 1 0 0 0 +}) + +// Get result as single line sequence format String with custom delimiter `*` (horizontal String) +.amplitudesAsSequence(Amplituda.SINGLE_LINE_SEQUENCE_FORMAT, " * ", customHorizontalSequenceString -> { + System.out.println(customHorizontalSequenceString); + // Output: 0 * 0 * 0 * 0 * 0 * 5 * 3 * 6 * . . . 6 * 4 * 7 * 1 * 0 * 0 * 0 +}) + +// Get result as new line sequence format String +.amplitudesAsSequence(Amplituda.NEW_LINE_SEQUENCE_FORMAT, newLineSequenceString -> { + System.out.println(newLineSequenceString); + /* Output: + 0 + 0 + 5 + 3 + . . . + 6 + 1 + 0 + 0 + */ +}); +``` + +### • Compress amplitudes (reduce output size) + +``` java +// When you call compressAmplitudes(/***/) - Amplituda will merge result amplitudes according to samplesPerSecond. +// After the call you will no longer be able to get previous Amplituda data + +// Input audio file duration is equal to 200 seconds (example) +amplituda.amplitudesAsList(amplitudes -> { + System.out.println(amplitudes.size()); + // Output: ~ 8000 +}) +// Amplituda result size is equal to 8000 samples here (before compressAmplituda call) +// . . . +// Pass the desired number of samples per second to the parameters. In this example - `1` sample per second +.compressAmplitudes(1) +// . . . +// Amplituda result size is equal to 200 samples here (after compressAmplituda call) +.amplitudesAsList(amplitudes -> { + System.out.println(amplitudes.size()); + // Output: ~ 200 +}); -## Maven -``` xml - - - jitpack.io - https://jitpack.io - - -``` -``` xml - - com.github.lincollincol - Amplituda - 1.7 - ``` -# Usage +### • Get duration from input file +``` java +System.out.printf( + Locale.getDefault(), + "Seconds: %d\nMillis: %d%n", + amplituda.getDuration(Amplituda.SECONDS), + amplituda.getDuration(Amplituda.MILLIS) +); +/* Output: +Seconds: 210 +Millis: 210000 +*/ +``` +### • Handle errors +All exceptions here -#### Example app here +``` java +amplituda.setErrorListener(error -> { + if(error instanceof AmplitudaIOException) { + System.out.println("IO Exception!"); + } +}); +``` -Amplituda library provide processed audio data to draw a waveform. You can get this data in different format: -* sequence (single/new line) -* json -* list of integers. +### • Enable Amplituda logs +``` java +// Use default android Log constants to set priority. The second parameter - enable or disable logs. +// Amplituda logs are disabled by default +amplituda.setLogConfig(Log.DEBUG, true); +``` ## Permissions Add permissions to Manifest.xml file in your app and grant it, before using Amplituda @@ -72,232 +158,46 @@ Add ``` android:extractNativeLibs="false" ``` to application in the Manifest.xml ``` -## Examples - -### • Get amplitudes from audio as json (String): - -#### Java -``` java -Amplituda amplituda = new Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesAsJson(json -> { - System.out.println("As json ====== " + json); - }); -// Output: [0, 0, 0, 0, 0, 5, 3, 6, . . . , 6, 4, 7, 1, 0, 0, 0] -``` -#### Kotlin -``` kotlin -val amplituda = Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesAsJson { - println("As json ====== $it") - } -// Output: [0, 0, 0, 0, 0, 5, 3, 6, . . . , 6, 4, 7, 1, 0, 0, 0] -``` - -### • Get amplitudes from audio as list of integers (List): - -#### Java -``` java -Amplituda amplituda = new Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesAsList(list -> { - System.out.print("As list ====== "); - for(int tmp : list) { - System.out.print(tmp + " "); - } - System.out.println(); - }); -// Output: 0 0 0 0 0 5 3 6 . . . 6 4 7 1 0 0 0 -``` -#### Kotlin -``` kotlin -val amplituda = Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesAsList { - print("As list ====== ") - for(tmp in it) { - print("$tmp ") - } - println() - } -// Output: 0 0 0 0 0 5 3 6 . . . 6 4 7 1 0 0 0 -``` - -### • Get amplitudes from audio as default single line sequence (String): - -#### Java -``` java -Amplituda amplituda = new Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesAsSequence(Amplituda.SINGLE_LINE_SEQUENCE_FORMAT, defSeq -> { - System.out.println("As sequence default ====== " + defSeq); - }); -// Output: 0 0 0 0 0 5 3 6 . . . 6 4 7 1 0 0 0 -``` -#### Kotlin -``` kotlin -val amplituda = Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesAsSequence(Amplituda.SINGLE_LINE_SEQUENCE_FORMAT) { - println("As sequence default ====== $it") - } -// Output: 0 0 0 0 0 5 3 6 . . . 6 4 7 1 0 0 0 -``` - -### • Get amplitudes from audio as custom single line sequence (String): - -#### Java -``` java -Amplituda amplituda = new Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesAsSequence(Amplituda.SINGLE_LINE_SEQUENCE_FORMAT, " * ", customSeq -> { - System.out.println("As sequence custom ====== " + customSeq); - }); -// Output: 0 * 0 * 0 * 0 * 0 * 5 * 3 * 6 * . . . 6 * 4 * 7 * 1 * 0 * 0 * 0 -``` -#### Kotlin -``` kotlin -val amplituda = Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesAsSequence(Amplituda.SINGLE_LINE_SEQUENCE_FORMAT, " * ") { - println("As sequence custom ====== $it") - } -// Output: 0 * 0 * 0 * 0 * 0 * 5 * 3 * 6 * . . . 6 * 4 * 7 * 1 * 0 * 0 * 0 -``` +#### Example app here -### • Get amplitudes from audio as new line sequence (String): - -#### Java -``` java -Amplituda amplituda = new Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesAsSequence(Amplituda.NEW_LINE_SEQUENCE_FORMAT, newLineSeq -> { - System.out.println("As sequence new line ====== " + newLineSeq); - }); -/* Output: -0 -0 -5 -3 -. . . -6 -1 -0 -0 -*/ -``` -#### Kotlin -``` kotlin -val amplituda = Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesAsSequence(Amplituda.NEW_LINE_SEQUENCE_FORMAT) { - println("As sequence new line ====== $it") - } -/* Output: -0 -0 -5 -3 -. . . -6 -1 -0 -0 -*/ -``` - -### • Get amplitudes per second -#### Java -``` java -Amplituda amplituda = new Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesPerSecond(5, list -> { - System.out.println(Arrays.toString(list.toArray())); - }); -/* Output: -[0, 0, 5, 3, . . . 6, 1, 0, 0] -*/ +## Download +### Gradle +``` groovy +allprojects { + repositories { + maven { url 'https://jitpack.io' } + } +} ``` -#### Kotlin -``` kotlin -val amplituda = Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") - .amplitudesPerSecond(5) { - println(Arrays.toString(list.toArray())) - } -/* Output: -[0, 0, 5, 3, . . . 6, 1, 0, 0] -*/ +``` groovy +dependencies { + implementation 'com.github.lincollincol:Amplituda:2.0.2' +} ``` -### • Get duration from input file -#### Java -``` java -Amplituda amplituda = new Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3"); -System.out.println(amplituda.getDuration(Amplituda.SECONDS)); -System.out.println(amplituda.getDuration(Amplituda.MILLIS)); -/* Output: -210 -210000 -*/ +### Maven +``` xml + + + jitpack.io + https://jitpack.io + + ``` -#### Kotlin -``` kotlin -val amplituda = Amplituda(context); -. . . -amplituda.fromPath("/storage/emulated/0/Music/Linc - Amplituda.mp3") -println(amplituda.getDuration(Amplituda.SECONDS)) -println(amplituda.getDuration(Amplituda.MILLIS)) -/* Output: -210 -210000 -*/ +``` xml + + com.github.lincollincol + Amplituda + 2.0.2 + ``` -### Supported formats (tested): -* mp3 -* wav -* opus -* oga -* ogg -* test more formats and contact me. - -## WARNING -### Amplituda process audio in the main thread ! You can run Amplituda with RxJava, Kotlin coroutines and Java Threads to process audio in the background therad. -Amplituda don't process audio in the background thread because of : -* You can use your own approach to work in the background thread. It makes Amplituda library more flexible. -* Reduce library size. Third-party library uses a lot of space and Amplituda delegates this task to user. - -## How to draw waveform -* You can use my WaveformSeekBar library fork in which Amplituda implemented. Example screenshot below: -

- -

- -* Use PlayerVisualizerView from this StackOverflow answer in which you should pass Amplituda data to ``` updateVisualizer() ``` as a parameter. -* Use another third-party library to draw waveform or create cutsom view in which this waveform view use processed audio data byAmplituda to draw every line. - ## Feedback linc.apps.sup@gmail.com # License ``` - Copyright 2020 lincollincol + Copyright 2020-present lincollincol Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/img/waveform_1.jpg b/img/waveform_1.jpg new file mode 100644 index 0000000..cc41207 Binary files /dev/null and b/img/waveform_1.jpg differ diff --git a/img/waveform_2.jpg b/img/waveform_2.jpg new file mode 100644 index 0000000..c44598c Binary files /dev/null and b/img/waveform_2.jpg differ diff --git a/img/waveform_3.jpg b/img/waveform_3.jpg new file mode 100644 index 0000000..4d03f9e Binary files /dev/null and b/img/waveform_3.jpg differ diff --git a/img/waveform_4.jpg b/img/waveform_4.jpg new file mode 100644 index 0000000..3af73fc Binary files /dev/null and b/img/waveform_4.jpg differ diff --git a/img/waveform_5.jpg b/img/waveform_5.jpg new file mode 100644 index 0000000..c3530ab Binary files /dev/null and b/img/waveform_5.jpg differ