Skip to content

Commit

Permalink
Merge branch 'dev-1.9'
Browse files Browse the repository at this point in the history
  • Loading branch information
birdofpreyru committed May 8, 2024
2 parents 33ea9d2 + 2ff871f commit d77e7e7
Show file tree
Hide file tree
Showing 27 changed files with 2,606 additions and 2,722 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defaults: &defaults
docker:
- image: cimg/node:lts

version: 2
version: 2.1
jobs:
test:
<<: *defaults
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v18
v20.12.2
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ enum class Errors(val message: String) {
}

override fun toString(): String {
return LOGTAG + ":" + name
return "${LOGTAG}:${name}"
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,24 @@ package com.drpogodin.reactnativeaudio

import android.media.AudioFormat
import android.media.AudioRecord
import kotlin.math.max

/**
* Represents an input audio stream.
* @param audioSource Audio source. Valid values are:
* https://developer.android.com/reference/android/media/MediaRecorder.AudioSource#summary
* @param sampleRate Sample rate (Hz). 44100 Hz is currently the only rate that is guaranteed
* to work on all devices. Zero value means the default rate, which is usually
* the audio source sample rate.
* @param channelConfig Valid values are:
* - AudioFormat.CHANNEL_IN_MONO
* - AudioFormat.CHANNEL_IN_STEREO
* @param audioFormat Valid values are:
* - AudioFormat.ENCODING_PCM_8BIT
* - AudioFormat.ENCODING_PCM_16BIT
* - AudioFormat.ENCODING_PCM_FLOAT
* @param samplingSize Number of samples in chunk (per channel).
* @param listener Chunk listener.
*/
class InputAudioStream internal constructor(audioSource: Int, sampleRate: Int, channelConfig: Int, audioFormat: Int,
samplingSize: Int, listener: Listener) {
Expand Down Expand Up @@ -36,61 +51,43 @@ class InputAudioStream internal constructor(audioSource: Int, sampleRate: Int, c
/**
* The execution thread.
*/
private val thread: Thread
private val thread: Thread = object : Thread() {
override fun run() {
var record: AudioRecord? = null
try {
// Initialization.
val frameSize = getNumChannels(channelConfig) * getSampleSize(audioFormat) // bytes
val chunkSize = frameSize * samplingSize // bytes
val chunk = ByteArray(chunkSize)
val minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat)
val bufferSize = max(3 * chunkSize, minBufferSize) // bytes
record = AudioRecord(audioSource, sampleRate, channelConfig, audioFormat,
bufferSize)
if (record.state != AudioRecord.STATE_INITIALIZED) {
throw Exception("Failed to start audio recording")
}
record.startRecording()

/**
* Creates and starts a new AudioStream.
* @param audioSource Audio source. Valid values are:
* https://developer.android.com/reference/android/media/MediaRecorder.AudioSource#summary
* @param sampleRate Sample rate [Hz]. 44100 Hz is currently the only rate that is guaranteed
* to work on all devices. Zero value means the default rate, which is usually
* the audio source sample rate.
* @param channelConfig Valid values are:
* - AudioFormat.CHANNEL_IN_MONO
* - AudioFormat.CHANNEL_IN_STEREO
* @param audioFormat Valid values are:
* - AudioFormat.ENCODING_PCM_8BIT
* - AudioFormat.ENCODING_PCM_16BIT
* - AudioFormat.ENCODING_PCM_FLOAT
* @param samplingSize Number of samples in chunk (per channel).
* @param listener Chunk listener.
*/
init {
thread = object : Thread() {
override fun run() {
var record: AudioRecord? = null
try {
// Initialization.
val frameSize = getNumChannels(channelConfig) * getSampleSize(audioFormat) // bytes
val chunkSize = frameSize * samplingSize // bytes
val chunk = ByteArray(chunkSize)
val minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat)
val bufferSize = Math.max(3 * chunkSize, minBufferSize) // bytes
record = AudioRecord(audioSource, sampleRate, channelConfig, audioFormat,
bufferSize)
if (record.state != AudioRecord.STATE_INITIALIZED) {
throw Exception("Failed to start audio recording")
}
record.startRecording()

// Main lifetime.
var chunkId = 0
while (!isInterrupted) {
record.read(chunk, 0, chunkSize)
if (!muted) listener.onChunk(chunkId, chunk)
++chunkId
}
// Main lifetime.
var chunkId = 0
while (!isInterrupted) {
record.read(chunk, 0, chunkSize)
if (!muted) listener.onChunk(chunkId, chunk)
++chunkId
}

// De-initialization.
record.stop()
} catch (e: SecurityException) {
listener.onError(e)
} catch (e: Exception) {
listener.onError(e)
}
record?.release()
}
// De-initialization.
record.stop()
} catch (e: SecurityException) {
listener.onError(e)
} catch (e: Exception) {
listener.onError(e)
}
record?.release()
}
}

init {
thread.start()
}

Expand Down Expand Up @@ -118,9 +115,9 @@ class InputAudioStream internal constructor(audioSource: Int, sampleRate: Int, c
}

/**
* Returns sample size [bytes] for the given audio format.
* Returns sample size (bytes) for the given audio format.
* @param audioFormat
* @return Sample size [bytes].
* @return Sample size (bytes).
* @throws Exception
*/
@Throws(Exception::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import android.media.AudioFormat
import android.media.AudioManager
import android.media.MediaRecorder
import android.os.Build
import android.util.Base64
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.Promise
Expand Down Expand Up @@ -37,11 +38,19 @@ class ReactNativeAudioModule internal constructor(context: ReactApplicationConte
constants["AUDIO_SOURCE_DEFAULT"] = MediaRecorder.AudioSource.DEFAULT
constants["AUDIO_SOURCE_MIC"] = MediaRecorder.AudioSource.MIC
constants["AUDIO_SOURCE_REMOTE_SUBMIX"] = MediaRecorder.AudioSource.REMOTE_SUBMIX
constants["AUDIO_SOURCE_UNPROCESSED"] = MediaRecorder.AudioSource.UNPROCESSED

constants["AUDIO_SOURCE_UNPROCESSED"] =
if (Build.VERSION.SDK_INT >= 24) MediaRecorder.AudioSource.UNPROCESSED
else MediaRecorder.AudioSource.DEFAULT

constants["AUDIO_SOURCE_VOICE_CALL"] = MediaRecorder.AudioSource.VOICE_CALL
constants["AUDIO_SOURCE_VOICE_COMMUNICATION"] = MediaRecorder.AudioSource.VOICE_COMMUNICATION
constants["AUDIO_SOURCE_VOICE_DOWNLINK"] = MediaRecorder.AudioSource.VOICE_DOWNLINK
constants["AUDIO_SOURCE_VOICE_PERFORMANCE"] = MediaRecorder.AudioSource.VOICE_PERFORMANCE

constants["AUDIO_SOURCE_VOICE_PERFORMANCE"] =
if (Build.VERSION.SDK_INT >= 29) MediaRecorder.AudioSource.VOICE_PERFORMANCE
else MediaRecorder.AudioSource.DEFAULT

constants["AUDIO_SOURCE_VOICE_RECOGNITION"] = MediaRecorder.AudioSource.VOICE_RECOGNITION
constants["AUDIO_SOURCE_VOICE_UPLINK"] = MediaRecorder.AudioSource.VOICE_UPLINK

Expand All @@ -55,11 +64,12 @@ class ReactNativeAudioModule internal constructor(context: ReactApplicationConte

@ReactMethod
override fun getInputAvailable(promise: Promise) {
val ctxt: Context = getReactApplicationContext().getApplicationContext()
val ctxt: Context = reactApplicationContext.applicationContext
val manager = ctxt.getSystemService(
Context.AUDIO_SERVICE) as AudioManager
try {
promise.resolve(manager.microphones.size > 0)
if (Build.VERSION.SDK_INT >= 28) promise.resolve(manager.microphones.size > 0)
else Errors.NOT_IMPLEMENTED.reject(promise, "Requires Android SDK 28 or above")
} catch (e: IOException) {
val msg = "Failed to get microphone list"
promise.reject(
Expand All @@ -73,7 +83,7 @@ class ReactNativeAudioModule internal constructor(context: ReactApplicationConte
* Sets up and runs an input audio stream.
* @param audioSource Audio source. Valid values are:
* https://developer.android.com/reference/android/media/MediaRecorder.AudioSource#summary
* @param sampleRate Sample rate [Hz]. 44100 Hz is currently the only rate that is guaranteed
* @param sampleRate Sample rate (Hz). 44100 Hz is currently the only rate that is guaranteed
* to work on all devices. Zero value means the default rate, which is usually
* the audio source sample rate.
* @param channelConfig Valid values are:
Expand All @@ -96,7 +106,7 @@ class ReactNativeAudioModule internal constructor(context: ReactApplicationConte
samplingSize: Double,
promise: Promise
) {
val emitter: DeviceEventManagerModule.RCTDeviceEventEmitter = getReactApplicationContext()
val emitter: DeviceEventManagerModule.RCTDeviceEventEmitter = reactApplicationContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
val stream = InputAudioStream(audioSource.toInt(), sampleRate.toInt(), channelConfig.toInt(), audioFormat.toInt(), samplingSize.toInt(),
object : InputAudioStream.Listener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import com.facebook.react.bridge.Promise

class SamplePlayer internal constructor() : SoundPool.OnLoadCompleteListener {
private val loadPromises = HashMap<Int, Promise>()
private val pool: SoundPool
private val pool: SoundPool = builder!!.build()
private val soundIds = HashMap<String, Int>()
private val streamIds = HashMap<String, Int>()

init {
pool = builder!!.build()
pool.setOnLoadCompleteListener(this)
}

Expand Down
2 changes: 1 addition & 1 deletion android/src/oldarch/ReactNativeAudioSpec.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.drpogodin.reactnativeaudio

import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.Promise

abstract class ReactNativeAudioSpec(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) {
abstract override fun getName(): String
Expand Down
6 changes: 4 additions & 2 deletions example/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.6.10"

gem 'cocoapods', '~> 1.13'
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
# bound in the template on Cocoapods with next React Native release.
gem 'cocoapods', '>= 1.13', '< 1.15'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
1 change: 0 additions & 1 deletion example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ android {
dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
implementation("com.facebook.react:flipper-integration")

if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ class MainActivity : ReactActivity() {
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
*/
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,28 @@ import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.flipper.ReactNativeFlipper
import com.facebook.soloader.SoLoader

class MainApplication : Application(), ReactApplication {

override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> {
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
return PackageList(this).packages
}
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
}

override fun getJSMainModuleName(): String = "index"
override fun getJSMainModuleName(): String = "index"

override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG

override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}

override val reactHost: ReactHost
get() = getDefaultReactHost(this.applicationContext, reactNativeHost)
get() = getDefaultReactHost(applicationContext, reactNativeHost)

override fun onCreate() {
super.onCreate()
Expand All @@ -40,6 +39,5 @@ class MainApplication : Application(), ReactApplication {
// If you opted-in for the New Architecture, we load the native entry point for this app.
load()
}
ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
android:insetTop="@dimen/abc_edit_text_inset_top_material"
android:insetBottom="@dimen/abc_edit_text_inset_bottom_material">
android:insetBottom="@dimen/abc_edit_text_inset_bottom_material"
>

<selector>
<!--
Expand Down
6 changes: 3 additions & 3 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
buildscript {
ext {
buildToolsVersion = "34.0.0"
minSdkVersion = 21
minSdkVersion = 23
compileSdkVersion = 34
targetSdkVersion = 34
ndkVersion = "25.1.8937393"
kotlinVersion = "1.8.0"
ndkVersion = "26.1.10909125"
kotlinVersion = "1.9.22"
}
repositories {
google()
Expand Down
2 changes: 1 addition & 1 deletion example/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
14 changes: 7 additions & 7 deletions example/android/gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,15 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
Expand Down Expand Up @@ -202,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.

set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
Expand Down
Loading

0 comments on commit d77e7e7

Please sign in to comment.