Skip to content

Commit

Permalink
feat(Android): Mute other audio streams when recording.
Browse files Browse the repository at this point in the history
closes #295, closes #276
  • Loading branch information
llfbandit committed May 21, 2024
2 parents 9093032 + e1addb6 commit 8ae6a56
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 4 deletions.
4 changes: 3 additions & 1 deletion record_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
## 1.2.0
* feat: Re-introduced native MediaRecorder. Set `RecordConfig.androidConfig.useLegacy` to `true`. This comes with limitations compared to advanced recorder.
* feat: Advanced AudioRecorder will try to adjust given configuration if unsupported or out of range (sample rate, bitrate and channel count).
Those two above should help for older devices or bad vendor implementations.
* Those two features should help for older devices, bad vendor implementations or misusage of configuration values.
* feat: ability to mute all audio streams when recording. The settings are restored when the recording is stopped.
* Notice: streams will stay at current state on pause/resume.

## 1.1.0
* fix: Properly close container when recording is stopped.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ class MethodCallHandlerImpl(
Utils.firstNonNull(call.argument("echoCancel"), false),
Utils.firstNonNull(call.argument("noiseSuppress"), false),
Utils.firstNonNull(androidConfig?.get("useLegacy") as Boolean?, false),
Utils.firstNonNull(androidConfig?.get("muteAudio") as Boolean?, false),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ internal class RecorderWrapper(

return AudioRecorder(
recorderStateStreamHandler,
recorderRecordStreamHandler
recorderRecordStreamHandler,
context
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class RecordConfig(
val echoCancel: Boolean = false,
val noiseSuppress: Boolean = false,
val useLegacy: Boolean = false,
val muteAudio: Boolean = false,
) {
val numChannels: Int = 2.coerceAtMost(1.coerceAtLeast(numChannels))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.llfbandit.record.record.recorder

import android.content.Context
import android.media.AudioManager
import android.util.Log
import com.llfbandit.record.record.RecordConfig
import com.llfbandit.record.record.RecordState
import com.llfbandit.record.record.stream.RecorderRecordStreamHandler
import com.llfbandit.record.record.stream.RecorderStateStreamHandler


interface OnAudioRecordListener {
fun onRecord()
fun onPause()
Expand All @@ -17,27 +20,53 @@ interface OnAudioRecordListener {
class AudioRecorder(
// Recorder streams
private val recorderStateStreamHandler: RecorderStateStreamHandler,
private val recorderRecordStreamHandler: RecorderRecordStreamHandler
private val recorderRecordStreamHandler: RecorderRecordStreamHandler,
private val appContext: Context
) : IRecorder, OnAudioRecordListener {
companion object {
private val TAG = AudioRecorder::class.java.simpleName
}

// Recorder thread with which we will interact
private var recorderThread: RecordThread? = null

// Amplitude
private var maxAmplitude = -160.0

// Recording config
private var config: RecordConfig? = null

// Stop callback to be synchronized between stop method return & record stop
private var stopCb: ((path: String?) -> Unit)? = null

private var muteSettings = HashMap<Int, Int>()
private val muteStreams = arrayOf(
AudioManager.STREAM_ALARM,
AudioManager.STREAM_DTMF,
AudioManager.STREAM_MUSIC,
AudioManager.STREAM_NOTIFICATION,
AudioManager.STREAM_RING,
AudioManager.STREAM_SYSTEM,
AudioManager.STREAM_VOICE_CALL,
)

init {
initMuteSettings()
}

/**
* Starts the recording with the given config.
*/
@Throws(Exception::class)
override fun start(config: RecordConfig) {
this.config = config

recorderThread = RecordThread(config, this)
recorderThread!!.startRecording()

if (config.muteAudio) {
muteAudio(true)
}
}

override fun stop(stopCb: ((path: String?) -> Unit)?) {
Expand Down Expand Up @@ -86,6 +115,10 @@ class AudioRecorder(
}

override fun onStop() {
if (config?.muteAudio == true) {
muteAudio(false)
}

stopCb?.invoke(config?.path)
stopCb = null

Expand All @@ -100,4 +133,26 @@ class AudioRecorder(
override fun onAudioChunk(chunk: ByteArray) {
recorderRecordStreamHandler.sendRecordChunkEvent(chunk)
}

private fun muteAudio(mute: Boolean) {
val audioManager = appContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager

val muteValue = -100 // AudioManager.ADJUST_MUTE
val unmuteValue = 100 // AudioManager.ADJUST_UNMUTE

muteStreams.forEach { stream ->
val volumeLevel = if (mute) muteValue else (muteSettings[stream] ?: unmuteValue)
audioManager.setStreamVolume(stream, volumeLevel, 0)
}
}

private fun initMuteSettings() {
muteSettings.clear()

val audioManager = appContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager

muteStreams.forEach { stream ->
muteSettings[stream] = audioManager.getStreamVolume(stream)
}
}
}
14 changes: 13 additions & 1 deletion record_platform_interface/lib/src/types/record_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,33 @@ class RecordConfig {
}
}

/// Android specific configuration
/// Android specific configuration for recording.
class AndroidRecordConfig {
/// Uses Android MediaRecorder if [true].
///
/// Uses advanced recorder with media codecs and additionnal features
/// by default.
final bool useLegacy;

/// If [true], this will mute all audio streams like alarms, music, ring, ...
///
/// This is useful when you want to record audio without any background noise.
///
/// The streams are restored to their previous state after recording is stopped
/// and will stay at current state on pause/resume.
///
/// Use at your own risks!
final bool muteAudio;

const AndroidRecordConfig({
this.useLegacy = false,
this.muteAudio = false,
});

Map<String, dynamic> toMap() {
return {
'useLegacy': useLegacy,
'muteAudio': muteAudio,
};
}
}

0 comments on commit 8ae6a56

Please sign in to comment.