Skip to content

Commit bb64154

Browse files
Merge pull request #77 from SimformSolutionsPvtLtd/develop
Release v2.1.0
2 parents 1e657f3 + 5d5c3d9 commit bb64154

35 files changed

+449
-139
lines changed

README.md

Lines changed: 62 additions & 55 deletions
Large diffs are not rendered by default.

android/build.gradle

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ buildscript {
88
}
99

1010
dependencies {
11-
classpath "com.android.tools.build:gradle:7.2.1"
11+
classpath "com.android.tools.build:gradle:8.1.0"
1212
// noinspection DifferentKotlinGradleVersion
1313
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
1414
}
@@ -71,8 +71,12 @@ android {
7171
}
7272

7373
compileOptions {
74-
sourceCompatibility JavaVersion.VERSION_1_8
75-
targetCompatibility JavaVersion.VERSION_1_8
74+
sourceCompatibility JavaVersion.VERSION_11
75+
targetCompatibility JavaVersion.VERSION_11
76+
}
77+
78+
kotlinOptions {
79+
jvmTarget = "11"
7680
}
7781
}
7882

@@ -93,6 +97,7 @@ dependencies {
9397
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
9498

9599

96-
// Android Audio Playback Dependency
97-
implementation "com.google.android.exoplayer:exoplayer:2.17.1"
100+
// Android Audio Media3 Dependency
101+
implementation 'androidx.media3:media3-exoplayer:1.3.1'
102+
implementation 'androidx.media3:media3-common:1.3.1'
98103
}

android/gradle.properties

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
AudioWaveform_kotlinVersion=1.7.0
1+
AudioWaveform_kotlinVersion=1.6.10
22
AudioWaveform_minSdkVersion=21
3-
AudioWaveform_targetSdkVersion=31
4-
AudioWaveform_compileSdkVersion=31
3+
AudioWaveform_targetSdkVersion=34
4+
AudioWaveform_compileSdkVersion=34
55
AudioWaveform_ndkversion=21.4.7075529
6+
android.suppressUnsupportedCompileSdk=34

android/src/main/java/com/audiowaveform/AudioPlayer.kt

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import com.facebook.react.bridge.ReactApplicationContext
88
import com.facebook.react.bridge.WritableMap
99
import com.facebook.react.common.JavascriptException
1010
import com.facebook.react.modules.core.DeviceEventManagerModule
11-
import com.google.android.exoplayer2.ExoPlayer
12-
import com.google.android.exoplayer2.MediaItem
13-
import com.google.android.exoplayer2.Player
11+
import androidx.media3.exoplayer.ExoPlayer
12+
import androidx.media3.common.MediaItem
13+
import androidx.media3.common.Player
1414

1515
class AudioPlayer(
1616
context: ReactApplicationContext,
@@ -25,8 +25,15 @@ class AudioPlayer(
2525
private var updateFrequency = UpdateFrequency.Low
2626
private lateinit var audioPlaybackListener: CountDownTimer
2727

28-
fun preparePlayer(path: String?, volume: Int?, frequency: UpdateFrequency, promise: Promise) {
28+
fun preparePlayer(
29+
path: String?,
30+
volume: Int?,
31+
frequency: UpdateFrequency,
32+
progress: Long,
33+
promise: Promise
34+
) {
2935
if (path != null) {
36+
isPlayerPrepared = false
3037
updateFrequency = frequency
3138
val uri = Uri.parse(path)
3239
val mediaItem = MediaItem.fromUri(uri)
@@ -41,6 +48,7 @@ class AudioPlayer(
4148
if (!isPlayerPrepared) {
4249
if (state == Player.STATE_READY) {
4350
player.volume = (volume ?: 1).toFloat()
51+
player.seekTo(progress)
4452
isPlayerPrepared = true
4553
val duration = player.duration
4654
promise.resolve(duration.toString())
@@ -97,7 +105,18 @@ class AudioPlayer(
97105
}
98106
}
99107

100-
fun start(finishMode: Int?, promise: Promise) {
108+
private fun validateAndSetPlaybackSpeed(player: Player, speed: Float?): Boolean {
109+
// Validate the speed: if null or less than or equal to 0, set to 1f
110+
val validSpeed = if (speed == null || speed <= 0f) 1f else speed
111+
112+
// Set the playback speed on the player
113+
val playbackParameters = player.playbackParameters.withSpeed(validSpeed)
114+
player.playbackParameters = playbackParameters
115+
116+
return true // Indicate success
117+
}
118+
119+
fun start(finishMode: Int?, speed: Float?, promise: Promise) {
101120
try {
102121
if (finishMode != null && finishMode == 0) {
103122
this.finishMode = FinishMode.Loop
@@ -106,6 +125,9 @@ class AudioPlayer(
106125
} else {
107126
this.finishMode = FinishMode.Stop
108127
}
128+
129+
validateAndSetPlaybackSpeed(player, speed)
130+
109131
player.playWhenReady = true
110132
player.play()
111133
promise.resolve(true)
@@ -150,6 +172,18 @@ class AudioPlayer(
150172
}
151173
}
152174

175+
fun setPlaybackSpeed(speed: Float?, promise: Promise) {
176+
try {
177+
// Call the custom function to validate and set the playback speed
178+
val success = validateAndSetPlaybackSpeed(player, speed)
179+
promise.resolve(success) // Resolve the promise with success
180+
181+
} catch (e: Exception) {
182+
// Handle any exceptions and reject the promise
183+
promise.reject("setPlaybackSpeed Error", e.toString())
184+
}
185+
}
186+
153187
private fun startListening(promise: Promise) {
154188
try {
155189
audioPlaybackListener = object : CountDownTimer(player.duration, UpdateFrequency.Low.value) {
@@ -172,4 +206,8 @@ class AudioPlayer(
172206
audioPlaybackListener.cancel()
173207
}
174208
}
209+
210+
fun isHoldingAudioTrack(): Boolean {
211+
return ::audioPlaybackListener.isInitialized
212+
}
175213
}

android/src/main/java/com/audiowaveform/AudioWaveformModule.kt

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class AudioWaveformModule(context: ReactApplicationContext): ReactContextBaseJav
3434

3535
companion object {
3636
const val NAME = "AudioWaveform"
37+
const val MAX_NUMBER_OF_AUDIO_PLAYER = 30
3738
}
3839

3940
override fun getName(): String {
@@ -100,16 +101,27 @@ class AudioWaveformModule(context: ReactApplicationContext): ReactContextBaseJav
100101
obj: ReadableMap,
101102
promise: Promise
102103
) {
104+
if(audioPlayers.filter { it.value?.isHoldingAudioTrack() == true }.count() >= MAX_NUMBER_OF_AUDIO_PLAYER) {
105+
promise.reject(Constants.LOG_TAG, "Too many players have been initialized. Please stop some players before continuing")
106+
}
107+
103108
val path = obj.getString(Constants.path)
104109
val key = obj.getString(Constants.playerKey)
105110
val frequency = obj.getInt(Constants.updateFrequency)
106111
val volume = obj.getInt(Constants.volume)
112+
val progress = if (!obj.hasKey(Constants.progress) || obj.isNull(Constants.progress)) {
113+
0 // Set default progress to zero if null, undefined, or missing
114+
} else {
115+
obj.getInt(Constants.progress).toLong()
116+
}
117+
107118
if (key != null) {
108119
initPlayer(key)
109120
audioPlayers[key]?.preparePlayer(
110121
path,
111122
volume,
112123
getUpdateFrequency(frequency),
124+
progress,
113125
promise
114126
)
115127
} else {
@@ -121,8 +133,9 @@ class AudioWaveformModule(context: ReactApplicationContext): ReactContextBaseJav
121133
fun startPlayer(obj: ReadableMap, promise: Promise) {
122134
val finishMode = obj.getInt(Constants.finishMode)
123135
val key = obj.getString(Constants.playerKey)
136+
val speed = obj.getDouble(Constants.speed)
124137
if (key != null) {
125-
audioPlayers[key]?.start(finishMode ?: 2, promise)
138+
audioPlayers[key]?.start(finishMode ?: 2, speed.toFloat(),promise)
126139
} else {
127140
promise.reject("startPlayer Error", "Player key can't be null")
128141
}
@@ -133,6 +146,7 @@ class AudioWaveformModule(context: ReactApplicationContext): ReactContextBaseJav
133146
val key = obj.getString(Constants.playerKey)
134147
if (key != null) {
135148
audioPlayers[key]?.stop(promise)
149+
audioPlayers[key] = null // Release the player after stopping it
136150
} else {
137151
promise.reject("stopPlayer Error", "Player key can't be null")
138152
}
@@ -209,6 +223,23 @@ class AudioWaveformModule(context: ReactApplicationContext): ReactContextBaseJav
209223
}
210224
}
211225

226+
@ReactMethod
227+
fun setPlaybackSpeed(obj: ReadableMap, promise: Promise) {
228+
// If the key doesn't exist or if the value is null or undefined, set default speed to 1.0
229+
val speed = if (!obj.hasKey(Constants.speed) || obj.isNull(Constants.speed)) {
230+
1.0f // Set default speed to 1.0 if null, undefined, or missing
231+
} else {
232+
obj.getDouble(Constants.speed).toFloat()
233+
}
234+
235+
val key = obj.getString(Constants.playerKey)
236+
if (key != null) {
237+
audioPlayers[key]?.setPlaybackSpeed(speed, promise)
238+
} else {
239+
promise.reject("setPlaybackSpeed Error", "Player key can't be null")
240+
}
241+
}
242+
212243
private fun initPlayer(playerKey: String) {
213244
if (audioPlayers[playerKey] == null) {
214245
val newPlayer = AudioPlayer(

android/src/main/java/com/audiowaveform/Utils.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ object Constants {
4343
const val currentDecibel = "currentDecibel"
4444
const val bitRate = "bitRate"
4545
const val sampleRate = "sampleRate"
46+
const val speed = "speed"
4647
}
4748

4849
enum class FinishMode(val value:Int) {

android/src/main/java/com/audiowaveform/WaveformExtractor.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import java.nio.ByteBuffer
1616
import java.util.concurrent.CountDownLatch
1717
import kotlin.math.pow
1818
import kotlin.math.sqrt
19+
import java.io.File
1920

2021
class WaveformExtractor(
2122
context: ReactApplicationContext,
@@ -66,6 +67,11 @@ class WaveformExtractor(
6667

6768
fun startDecode() {
6869
try {
70+
if (!File(path).exists()) {
71+
promise.reject("File Error", "File does not exist at the given path.")
72+
return
73+
}
74+
6975
val format = getFormat(path) ?: error("No audio format found")
7076
val mime = format.getString(MediaFormat.KEY_MIME) ?: error("No MIME type found")
7177
decoder = MediaCodec.createDecoderByType(mime).also {

assets/audio_playback.gif

-3.8 MB
Loading
12.1 MB
Loading

assets/audio_record.gif

-237 KB
Loading

0 commit comments

Comments
 (0)