From dde6db4c9d5f5f12d2774cf6bfe8a6829d2c02dc Mon Sep 17 00:00:00 2001 From: ThibaultBee <37510686+ThibaultBee@users.noreply.github.com> Date: Sun, 17 Nov 2024 21:21:25 +0100 Subject: [PATCH] feat(*): add new audio effects --- .../audio/audiorecord/AudioRecordEffect.kt | 138 +++++++++++++ .../{ => audiorecord}/AudioRecordSource.kt | 181 ++++++++++-------- .../audio/audiorecord/IAudioRecordSource.kt | 56 ++++++ .../MediaProjectionAudioSource.kt | 14 +- .../{ => audiorecord}/MicrophoneSource.kt | 28 ++- .../utils/extensions/AudioEffectExtensions.kt | 22 +++ .../streamers/DefaultAudioOnlyStreamer.kt | 4 +- .../core/streamers/DefaultCameraStreamer.kt | 4 +- .../DefaultScreenRecorderStreamer.kt | 4 +- .../internal/sources/AudioCaptureUnitTest.kt | 2 +- 10 files changed, 348 insertions(+), 105 deletions(-) create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/AudioRecordEffect.kt rename core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/{ => audiorecord}/AudioRecordSource.kt (60%) create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/IAudioRecordSource.kt rename core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/{ => audiorecord}/MediaProjectionAudioSource.kt (82%) rename core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/{ => audiorecord}/MicrophoneSource.kt (71%) create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/core/internal/utils/extensions/AudioEffectExtensions.kt diff --git a/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/AudioRecordEffect.kt b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/AudioRecordEffect.kt new file mode 100644 index 000000000..d311d93f6 --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/AudioRecordEffect.kt @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2021 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord + +import android.media.audiofx.AcousticEchoCanceler +import android.media.audiofx.AudioEffect +import android.media.audiofx.AutomaticGainControl +import android.media.audiofx.BassBoost +import android.media.audiofx.NoiseSuppressor +import android.os.Build +import java.util.UUID + +/** + * Audio effect interface + */ +internal class AudioRecordEffect { + internal interface IFactory { + fun build(audioSessionId: Int): AudioEffect? + } + + companion object { + private const val TAG = "AudioRecordEffect" + + fun getSupportedEffects(): List { + val descriptors = AudioEffect.queryEffects() + return descriptors.map { it.type } + } + } + + internal abstract class Factory : IFactory { + protected abstract val name: String + + protected abstract fun isAvailable(): Boolean + protected abstract fun create(audioSessionId: Int): T? + protected fun applyConfigurationFrom(audioEffect: T) = Unit + + override fun build(audioSessionId: Int): T { + if (!isAvailable()) { + throw IllegalStateException("$name is not available") + } + + val audioEffect = try { + create(audioSessionId) + } catch (t: Throwable) { + throw Exception("Failed to create $name", t) + } + + requireNotNull(audioEffect) { + "Failed to create $name" + } + + val result = audioEffect.setEnabled(true) + if (result != AudioEffect.SUCCESS) { + audioEffect.release() + throw Exception("Failed to enable $name") + } + + return audioEffect + } + + companion object { + fun getFactoryForEffectType(effectType: UUID): Factory<*> { + return when (effectType) { + AudioEffect.EFFECT_TYPE_AEC -> AcousticEchoCancelerFactory() + AudioEffect.EFFECT_TYPE_AGC -> AutomaticGainControlFactory() + AudioEffect.EFFECT_TYPE_BASS_BOOST -> BassBoostFactory() + AudioEffect.EFFECT_TYPE_NS -> NoiseSuppressorFactory() + else -> throw IllegalArgumentException("Unknown effect type: $effectType") + } + } + + fun isValidUUID(uuid: UUID): Boolean { + return uuid == AudioEffect.EFFECT_TYPE_AEC || + uuid == AudioEffect.EFFECT_TYPE_AGC || + uuid == AudioEffect.EFFECT_TYPE_BASS_BOOST || + ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) && + uuid == AudioEffect.EFFECT_TYPE_DYNAMICS_PROCESSING) || + uuid == AudioEffect.EFFECT_TYPE_ENV_REVERB || + uuid == AudioEffect.EFFECT_TYPE_EQUALIZER || + ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) && + uuid == AudioEffect.EFFECT_TYPE_HAPTIC_GENERATOR) || + uuid == AudioEffect.EFFECT_TYPE_LOUDNESS_ENHANCER || + uuid == AudioEffect.EFFECT_TYPE_NS || + uuid == AudioEffect.EFFECT_TYPE_PRESET_REVERB || + uuid == AudioEffect.EFFECT_TYPE_VIRTUALIZER + } + } + } + + internal class AcousticEchoCancelerFactory : Factory() { + override val name: String = "Acoustic echo canceler" + + override fun isAvailable(): Boolean = AcousticEchoCanceler.isAvailable() + + override fun create(audioSessionId: Int): AcousticEchoCanceler? = + AcousticEchoCanceler.create(audioSessionId) + } + + internal class AutomaticGainControlFactory : Factory() { + override val name: String = "Automatic gain control" + + override fun isAvailable(): Boolean = AutomaticGainControl.isAvailable() + + override fun create(audioSessionId: Int): AutomaticGainControl? = + AutomaticGainControl.create(audioSessionId) + } + + internal class BassBoostFactory(private val priority: Int = 0) : Factory() { + override val name: String = "Bass boost" + + override fun isAvailable(): Boolean = + getSupportedEffects().contains(AudioEffect.EFFECT_TYPE_BASS_BOOST) + + override fun create(audioSessionId: Int) = BassBoost(priority, audioSessionId) + } + + internal class NoiseSuppressorFactory : Factory() { + override val name: String = "Noise suppressor" + + override fun isAvailable(): Boolean = NoiseSuppressor.isAvailable() + + override fun create(audioSessionId: Int): NoiseSuppressor? = + NoiseSuppressor.create(audioSessionId) + } +} diff --git a/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/AudioRecordSource.kt b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/AudioRecordSource.kt similarity index 60% rename from core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/AudioRecordSource.kt rename to core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/AudioRecordSource.kt index a06a94e2c..21383086a 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/AudioRecordSource.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/AudioRecordSource.kt @@ -13,37 +13,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.core.internal.sources.audio +package io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord import android.Manifest import android.media.AudioRecord import android.media.AudioTimestamp import android.media.MediaFormat -import android.media.audiofx.AcousticEchoCanceler -import android.media.audiofx.NoiseSuppressor +import android.media.audiofx.AudioEffect import android.os.Build import androidx.annotation.RequiresPermission import io.github.thibaultbee.streampack.core.data.AudioConfig import io.github.thibaultbee.streampack.core.internal.data.Frame -import io.github.thibaultbee.streampack.core.internal.sources.IFrameSource +import io.github.thibaultbee.streampack.core.internal.sources.audio.IAudioSourceInternal +import io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord.AudioRecordEffect.Factory.Companion.getFactoryForEffectType +import io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord.AudioRecordEffect.Factory.Companion.isValidUUID import io.github.thibaultbee.streampack.core.internal.utils.TimeUtils +import io.github.thibaultbee.streampack.core.internal.utils.extensions.type import io.github.thibaultbee.streampack.core.logger.Logger import java.nio.ByteBuffer +import java.util.UUID /** * The [AudioRecordSource] class is an implementation of [IAudioSourceInternal] that captures audio * from [AudioRecord]. * - * @param enableAcousticEchoCanceler [Boolean.true] to enable AcousticEchoCanceler - * @param enableNoiseSuppressor [Boolean.true] to enable NoiseSuppressor + * @param defaultEffects [List] of default effects type to enable. Default is [AudioEffect.EFFECT_TYPE_AEC] and [AudioEffect.EFFECT_TYPE_NS]. */ -sealed class AudioRecordSource( - private val enableAcousticEchoCanceler: Boolean = true, - private val enableNoiseSuppressor: Boolean = true -) : IAudioSourceInternal, IFrameSource { +sealed class AudioRecordSource : IAudioSourceInternal, IAudioRecordSourceSource { private var audioRecord: AudioRecord? = null - private var processor: EffectProcessor? = null + private var processor = EffectProcessor() private var mutedByteArray: ByteArray? = null override var isMuted: Boolean = false @@ -87,11 +86,7 @@ sealed class AudioRecordSource( mutedByteArray = ByteArray(bufferSize) audioRecord = buildAudioRecord(config, bufferSize).also { - processor = EffectProcessor( - enableAcousticEchoCanceler, - enableNoiseSuppressor, - it.audioSessionId - ) + processor.audioSessionId = it.audioSessionId if (it.state != AudioRecord.STATE_INITIALIZED) { throw IllegalArgumentException("Failed to initialized audio source with config: $config") @@ -117,12 +112,11 @@ sealed class AudioRecordSource( override fun release() { mutedByteArray = null + processor.clear() + // Release audio record audioRecord?.release() audioRecord = null - - processor?.release() - processor = null } private fun getTimestamp(audioRecord: AudioRecord): Long { @@ -182,6 +176,36 @@ sealed class AudioRecordSource( else -> "Unknown audio record error: $audioRecordError" } + /** + * Adds and enables an effect to the audio source. + * + * Get supported effects with [getSupportedEffectTypes]. + */ + override fun addEffect(effectType: UUID): AudioEffect { + return processor.add(effectType) + } + + /** + * Removes an effect from the audio source. + */ + override fun removeEffect(effectType: UUID) { + processor.remove(effectType) + } + + /** + * Gets an effect from the audio source. + */ + override fun getEffect(effectType: UUID): AudioEffect { + return processor.get(effectType) + } + + /** + * Gets all effects from the audio source. + */ + override fun getEffects(): List { + return processor.getAll().toList() + } + companion object { private const val TAG = "AudioSource" @@ -191,81 +215,82 @@ sealed class AudioRecordSource( MediaFormat.MIMETYPE_AUDIO_RAW ) } + + /** + * Get supported effects. + * + * @return [List] of supported effects. + * @see AudioEffect + */ + fun getSupportedEffectTypes(): List { + return AudioRecordEffect.getSupportedEffects() + } } - private class EffectProcessor( - enableAcousticEchoCanceler: Boolean, - enableNoiseSuppressor: Boolean, - audioSessionId: Int - ) { - private val acousticEchoCanceler = - if (enableAcousticEchoCanceler) initAcousticEchoCanceler(audioSessionId) else null - private val noiseSuppressor = - if (enableNoiseSuppressor) initNoiseSuppressor(audioSessionId) else null + private class EffectProcessor { + private val audioEffects: MutableSet = mutableSetOf() + var audioSessionId: Int = AudioRecord.ERROR_BAD_VALUE + set(value) { + require(value != AudioRecord.ERROR_BAD_VALUE) { "Invalid audio session id" } - fun release() { - acousticEchoCanceler?.release() - noiseSuppressor?.release() - } + // Adds previous effects to new audio session + val previousEffectTypes = audioEffects.map { it.type } + clear() - companion object { - private fun initNoiseSuppressor(audioSessionId: Int): NoiseSuppressor? { - if (!NoiseSuppressor.isAvailable()) { - Logger.w(TAG, "Noise suppressor is not available") - return null - } + previousEffectTypes.forEach { add(it) } + field = value + } - val noiseSuppressor = try { - NoiseSuppressor.create(audioSessionId) - } catch (t: Throwable) { - Logger.e(TAG, "Failed to create noise suppressor", t) - return null - } + fun get(effectType: UUID): AudioEffect { + require(isValidUUID(effectType)) { "Unknown effect type: $effectType" } - if (noiseSuppressor == null) { - Logger.w(TAG, "Failed to create noise suppressor") - return null - } + return audioEffects.firstOrNull { it.type == effectType } + ?: throw IllegalArgumentException("Effect $effectType not enabled") + } - val result = noiseSuppressor.setEnabled(true) - if (result != NoiseSuppressor.SUCCESS) { - noiseSuppressor.release() - Logger.w(TAG, "Failed to enable noise suppressor") - return null - } + fun getAll(): List { + return audioEffects.toList() + } - return noiseSuppressor + fun add(effectType: UUID): AudioEffect { + require(isValidUUID(effectType)) { "Unknown effect type: $effectType" } + + val previousEffect = audioEffects.firstOrNull { it.type == effectType } + if (previousEffect != null) { + Logger.w(TAG, "Effect ${previousEffect.descriptor.name} already enabled") + return previousEffect } - private fun initAcousticEchoCanceler(audioSessionId: Int): AcousticEchoCanceler? { - if (!AcousticEchoCanceler.isAvailable()) { - Logger.w(TAG, "Acoustic echo canceler is not available") - return null - } + val factory = getFactoryForEffectType(effectType) + factory.build(audioSessionId).let { + audioEffects.add(it) + return it + } + } - val acousticEchoCanceler = try { - AcousticEchoCanceler.create(audioSessionId) - } catch (t: Throwable) { - Logger.e(TAG, "Failed to create acoustic echo canceler", t) - return null - } + fun remove(effectType: UUID) { + require(isValidUUID(effectType)) { "Unknown effect type: $effectType" } - if (acousticEchoCanceler == null) { - Logger.w(TAG, "Failed to create acoustic echo canceler") - return null - } + val effect = audioEffects.firstOrNull { it.descriptor.type == effectType } + if (effect != null) { + effect.release() + audioEffects.remove(effect) + } + } - val result = acousticEchoCanceler.setEnabled(true) - if (result != AcousticEchoCanceler.SUCCESS) { - acousticEchoCanceler.release() - Logger.w(TAG, "Failed to enable acoustic echo canceler") - return null - } + fun release() { + audioEffects.forEach { it.release() } + } - return acousticEchoCanceler - } + fun clear() { + release() + audioEffects.clear() + } + + companion object { + private const val TAG = "EffectProcessor" } } } \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/IAudioRecordSource.kt b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/IAudioRecordSource.kt new file mode 100644 index 000000000..9d58f6608 --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/IAudioRecordSource.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2024 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord + +import android.media.audiofx.AudioEffect +import io.github.thibaultbee.streampack.core.internal.sources.audio.IAudioSource +import java.util.UUID + +interface IAudioRecordSourceSource : IAudioSource { + /** + * Adds an effect to the audio source. + * + * @param effectType The UUID of the effect to add + * @return The [AudioEffect] created in case you have to configure it + */ + fun addEffect(effectType: UUID): AudioEffect + + /** + * Removes an effect from the audio source. + * + * @param effectType The UUID of the effect to remove + */ + fun removeEffect(effectType: UUID) + + /** + * Gets an effect from the audio source. + * + * @param effectType The UUID of the effect to get + * @return The [AudioEffect] created in case you have to configure it + */ + fun getEffect(effectType: UUID): AudioEffect + + /** + * Gets all effects from the audio source. + * + * @return The list of [AudioEffect] + */ + fun getEffects(): List +} + +fun IAudioRecordSourceSource.getEffectTypes(): List { + return getEffects().map { it.descriptor.type } +} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/MediaProjectionAudioSource.kt b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/MediaProjectionAudioSource.kt similarity index 82% rename from core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/MediaProjectionAudioSource.kt rename to core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/MediaProjectionAudioSource.kt index 8103b471b..4b787e93d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/MediaProjectionAudioSource.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/MediaProjectionAudioSource.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.core.internal.sources.audio +package io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord import android.content.Context import android.media.AudioAttributes @@ -33,18 +33,12 @@ import io.github.thibaultbee.streampack.core.internal.sources.IMediaProjectionSo * captures audio played by other apps. * * @param context The application context - * @param enableAcousticEchoCanceler [Boolean.true] to enable AcousticEchoCanceler - * @param enableNoiseSuppressor [Boolean.true] to enable NoiseSuppressor */ @RequiresApi(Build.VERSION_CODES.Q) fun MediaProjectionAudioSource( context: Context, - enableAcousticEchoCanceler: Boolean = true, - enableNoiseSuppressor: Boolean = true ) = MediaProjectionAudioSource( context.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager, - enableAcousticEchoCanceler, - enableNoiseSuppressor ) /** @@ -52,15 +46,11 @@ fun MediaProjectionAudioSource( * captures audio played by other apps. * * @param mediaProjectionManager The media projection manager - * @param enableAcousticEchoCanceler [Boolean.true] to enable AcousticEchoCanceler - * @param enableNoiseSuppressor [Boolean.true] to enable NoiseSuppressor */ @RequiresApi(Build.VERSION_CODES.Q) class MediaProjectionAudioSource( private val mediaProjectionManager: MediaProjectionManager, - private val enableAcousticEchoCanceler: Boolean = true, - private val enableNoiseSuppressor: Boolean = true -) : AudioRecordSource(enableAcousticEchoCanceler, enableNoiseSuppressor), IMediaProjectionSource { +) : AudioRecordSource(), IMediaProjectionSource { private var mediaProjection: MediaProjection? = null /** diff --git a/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/MicrophoneSource.kt b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/MicrophoneSource.kt similarity index 71% rename from core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/MicrophoneSource.kt rename to core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/MicrophoneSource.kt index ed652d115..5335e9e28 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/MicrophoneSource.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/sources/audio/audiorecord/MicrophoneSource.kt @@ -13,25 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.core.internal.sources.audio +package io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord import android.media.AudioFormat import android.media.AudioRecord import android.media.MediaRecorder +import android.media.audiofx.AudioEffect import android.os.Build import io.github.thibaultbee.streampack.core.data.AudioConfig /** * The [MicrophoneSource] class is an implementation of [AudioRecordSource] that captures audio * from the microphone. - * - * @param enableAcousticEchoCanceler [Boolean.true] to enable AcousticEchoCanceler - * @param enableNoiseSuppressor [Boolean.true] to enable NoiseSuppressor */ -class MicrophoneSource( - private val enableAcousticEchoCanceler: Boolean = true, - private val enableNoiseSuppressor: Boolean = true -) : AudioRecordSource(enableAcousticEchoCanceler, enableNoiseSuppressor) { +class MicrophoneSource : AudioRecordSource() { override fun buildAudioRecord(config: AudioConfig, bufferSize: Int): AudioRecord { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { val audioFormat = AudioFormat.Builder() @@ -55,4 +50,21 @@ class MicrophoneSource( ) } } + + companion object { + /** + * Build a [MicrophoneSource] with default effects. + */ + fun buildDefaultMicrophoneSource(): MicrophoneSource { + val supportedAudioEffects = AudioRecordEffect.getSupportedEffects() + return MicrophoneSource().apply { + if (supportedAudioEffects.contains(AudioEffect.EFFECT_TYPE_AEC)) { + addEffect(AudioEffect.EFFECT_TYPE_AEC) + } + if (supportedAudioEffects.contains(AudioEffect.EFFECT_TYPE_NS)) { + addEffect(AudioEffect.EFFECT_TYPE_NS) + } + } + } + } } \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/core/internal/utils/extensions/AudioEffectExtensions.kt b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/utils/extensions/AudioEffectExtensions.kt new file mode 100644 index 000000000..936f0887a --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/core/internal/utils/extensions/AudioEffectExtensions.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.core.internal.utils.extensions + +import android.media.audiofx.AudioEffect +import java.util.UUID + +val AudioEffect.type: UUID + get() = descriptor.type \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultAudioOnlyStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultAudioOnlyStreamer.kt index 933a4ea16..b00c5b46d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultAudioOnlyStreamer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultAudioOnlyStreamer.kt @@ -19,7 +19,7 @@ import android.content.Context import io.github.thibaultbee.streampack.core.internal.endpoints.DynamicEndpoint import io.github.thibaultbee.streampack.core.internal.endpoints.IEndpointInternal import io.github.thibaultbee.streampack.core.internal.sources.audio.IAudioSourceInternal -import io.github.thibaultbee.streampack.core.internal.sources.audio.MicrophoneSource +import io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord.MicrophoneSource.Companion.buildDefaultMicrophoneSource /** * A [DefaultStreamer] that sends only microphone frames. @@ -29,7 +29,7 @@ import io.github.thibaultbee.streampack.core.internal.sources.audio.MicrophoneSo */ open class DefaultAudioOnlyStreamer( context: Context, - audioSourceInternal: IAudioSourceInternal? = MicrophoneSource(), + audioSourceInternal: IAudioSourceInternal? = buildDefaultMicrophoneSource(), internalEndpoint: IEndpointInternal = DynamicEndpoint(context) ) : DefaultStreamer( context = context, diff --git a/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultCameraStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultCameraStreamer.kt index ba64741a2..dc3bfcc05 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultCameraStreamer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultCameraStreamer.kt @@ -23,7 +23,7 @@ import io.github.thibaultbee.streampack.core.data.mediadescriptor.MediaDescripto import io.github.thibaultbee.streampack.core.internal.endpoints.DynamicEndpoint import io.github.thibaultbee.streampack.core.internal.endpoints.IEndpointInternal import io.github.thibaultbee.streampack.core.internal.sources.audio.IAudioSourceInternal -import io.github.thibaultbee.streampack.core.internal.sources.audio.MicrophoneSource +import io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord.MicrophoneSource.Companion.buildDefaultMicrophoneSource import io.github.thibaultbee.streampack.core.internal.sources.video.camera.CameraSource import io.github.thibaultbee.streampack.core.internal.sources.video.camera.ICameraSource import io.github.thibaultbee.streampack.core.streamers.infos.CameraStreamerConfigurationInfo @@ -43,7 +43,7 @@ fun DefaultCameraStreamer( internalEndpoint: IEndpointInternal = DynamicEndpoint(context) ) = DefaultCameraStreamer( context, - if (enableMicrophone) MicrophoneSource() else null, + if (enableMicrophone) buildDefaultMicrophoneSource() else null, internalEndpoint ) diff --git a/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultScreenRecorderStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultScreenRecorderStreamer.kt index 95e350527..6a36c668a 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultScreenRecorderStreamer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/core/streamers/DefaultScreenRecorderStreamer.kt @@ -25,7 +25,7 @@ import io.github.thibaultbee.streampack.core.internal.endpoints.DynamicEndpoint import io.github.thibaultbee.streampack.core.internal.endpoints.IEndpointInternal import io.github.thibaultbee.streampack.core.internal.sources.IMediaProjectionSource import io.github.thibaultbee.streampack.core.internal.sources.audio.IAudioSourceInternal -import io.github.thibaultbee.streampack.core.internal.sources.audio.MicrophoneSource +import io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord.MicrophoneSource.Companion.buildDefaultMicrophoneSource import io.github.thibaultbee.streampack.core.internal.sources.video.mediaprojection.MediaProjectionVideoSource /** @@ -41,7 +41,7 @@ fun DefaultScreenRecorderStreamer( internalEndpoint: IEndpointInternal = DynamicEndpoint(context) ) = DefaultScreenRecorderStreamer( context, - if (enableMicrophone) MicrophoneSource() else null, + if (enableMicrophone) buildDefaultMicrophoneSource() else null, internalEndpoint ) diff --git a/core/src/test/java/io/github/thibaultbee/streampack/core/internal/sources/AudioCaptureUnitTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/core/internal/sources/AudioCaptureUnitTest.kt index 75b5f2769..bffef26a4 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/core/internal/sources/AudioCaptureUnitTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/core/internal/sources/AudioCaptureUnitTest.kt @@ -15,7 +15,7 @@ */ package io.github.thibaultbee.streampack.core.internal.sources -import io.github.thibaultbee.streampack.core.internal.sources.audio.MicrophoneSource +import io.github.thibaultbee.streampack.core.internal.sources.audio.audiorecord.MicrophoneSource import io.github.thibaultbee.streampack.core.logger.Logger import io.github.thibaultbee.streampack.core.internal.utils.FakeLogger import org.junit.Assert