diff --git a/src/Tizen.Multimedia/AudioManager/AudioStreamPolicy.cs b/src/Tizen.Multimedia/AudioManager/AudioStreamPolicy.cs index 9d450f638bb..0d8ada32706 100644 --- a/src/Tizen.Multimedia/AudioManager/AudioStreamPolicy.cs +++ b/src/Tizen.Multimedia/AudioManager/AudioStreamPolicy.cs @@ -15,7 +15,9 @@ */ using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; namespace Tizen.Multimedia { @@ -421,6 +423,104 @@ public bool HasStreamOnDevice(AudioDevice device) return isOn; } + /// + /// Sets the sound effect. + /// + /// + /// If is true, must be or + /// or . + /// And must not be null.
+ /// If is false, must be or + /// or . + ///
+ /// See . + /// A reference device for sound effect. + /// When is true, A reference device is null. + /// The current is not supported for sound effect with reference. + /// The has already been disposed. + /// 12 + public void SetSoundEffect(SoundEffectInfo info, bool withReference) + { + if (withReference) + { + var set = new SoundEffectType[] { SoundEffectType.ReferenceCopy, SoundEffectType.AecSpeex, SoundEffectType.AecWebrtc }; + if (!set.Contains(info.Type)) + { + Log.Error(Tag, $"Type={info.Type} is not supported for setting with reference."); + throw new ArgumentException($"{info.Type} is not supported for setting with reference."); + } + if (info.ReferenceDevice == null) + { + throw new ArgumentNullException(nameof(info.ReferenceDevice)); + } + + Log.Info(Tag, $"{info.ReferenceDevice}"); + + Interop.AudioStreamPolicy.SetSoundEffectWithReference(Handle, (SoundEffectWithReferenceNative)info.Type.ToNative(), + info.ReferenceDevice.Id).ThrowIfError("Failed to set audio effect with reference"); + } + else + { + var set = new SoundEffectType[] { SoundEffectType.NoiseSuppression, SoundEffectType.AutoGainControl, SoundEffectType.NsWithAgc }; + if (!set.Contains(info.Type)) + { + throw new ArgumentException($"{info.Type} is not supported for setting without reference."); + } + + Interop.AudioStreamPolicy.SetSoundEffect(Handle, info.Type.ToNative()). + ThrowIfError("Failed to set sound effect with reference"); + } + } + + /// + /// Gets the sound effect. + /// + /// + /// If is false, of returned value will be null. + /// + /// + /// The sound effect is not set yet.
+ /// - or -
+ /// There's no matched AudioDevice. + ///
+ /// Sound effect is not set yet. + /// The has already been disposed. + /// 12 + public SoundEffectInfo GetSoundEffect(bool withReference) + { + AudioManagerError ret = AudioManagerError.None; + SoundEffectInfo soundEffectInfo; + int deviceId = 0; + + if (withReference) + { + ret = Interop.AudioStreamPolicy.GetSoundEffectWithReference(Handle, out SoundEffectWithReferenceNative nativeEffect, out deviceId); + if (ret == AudioManagerError.InvalidParameter) + { + throw new InvalidOperationException("There's no sound effect with reference"); + } + ret.ThrowIfError("Failed to get sound effect with reference"); + + Log.Info(Tag, $"Device ID : {deviceId}"); + + soundEffectInfo = new SoundEffectInfo(nativeEffect.ToPublic(), + AudioManager.GetConnectedDevices().Where(d => d.Id == deviceId).Single()); + } + else + { + ret = Interop.AudioStreamPolicy.GetSoundEffect(Handle, out int nativeEffect); + if (ret == AudioManagerError.InvalidParameter) + { + throw new InvalidOperationException("There's no sound effect"); + } + ret.ThrowIfError("Failed to get sound effect"); + + soundEffectInfo = new SoundEffectInfo(((SoundEffectNative)nativeEffect).ToPublic()); + } + + return soundEffectInfo; + } + /// /// Releases all resources used by the . /// diff --git a/src/Tizen.Multimedia/AudioManager/SoundEffect.cs b/src/Tizen.Multimedia/AudioManager/SoundEffect.cs new file mode 100644 index 00000000000..25f6277eb02 --- /dev/null +++ b/src/Tizen.Multimedia/AudioManager/SoundEffect.cs @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; + +namespace Tizen.Multimedia +{ + /// + /// Specifies the sound effect types. + /// + /// 12 + public enum SoundEffectType + { + /// + /// Noise suppression for voice call. + /// + NoiseSuppression, + + /// + /// Auto Gain Control for normal capturing. + /// + AutoGainControl, + + /// + /// Noise suppression + Auto Gain Control. + /// + NsWithAgc, + + /// + /// Includes the output sound from the reference device in the recorded audio. + /// + /// + /// This effect should be used with . + /// + ReferenceCopy = 0x1001, + + /// + /// AEC (Acoustic Echo Cancellation) with Speex. + /// + /// + /// This effect should be used with . + /// + AecSpeex, + + /// + /// AEC (Acoustic Echo Cancellation) with WebRTC. + /// + /// + /// This effect should be used with . + /// + AecWebrtc + } + + /// + /// Specifies the sound effect information. + /// + /// 12 + public struct SoundEffectInfo + { + /// + /// Initializes a new instance of . + /// + /// The SoundEffectType. + /// Invalid input enum type. + /// 12 + public SoundEffectInfo(SoundEffectType type) + { + ValidationUtil.ValidateEnum(typeof(SoundEffectType), type, nameof(type)); + + Type = type; + ReferenceDevice = null; + } + + /// + /// Initializes a new instance of with a reference audio device. + /// + /// The SoundEffectType. + /// The AudioDevice to be refered. + /// 12 + public SoundEffectInfo(SoundEffectType type, AudioDevice device) + { + ValidationUtil.ValidateEnum(typeof(SoundEffectType), type, nameof(type)); + + Type = type; + ReferenceDevice = device; + } + + /// + /// The SoundEffectType. + /// + /// 12 + public SoundEffectType Type { get; } + + /// + /// The AudioDevice used by the SoundEffect as additional source of audio data. + /// + /// 12 + public AudioDevice ReferenceDevice { get; } + } + + [Flags] + internal enum SoundEffectNative + { + NoiseSuppression = 1, + AutoGainControl = 2 + } + + internal enum SoundEffectWithReferenceNative + { + ReferenceCopy = 1, + AecSpeex = 2, + AecWebrtc = 4 + } + + internal static class EnumExtensions + { + private const string Tag = "Tizen.Multimedia.AudioManager"; + + internal static int ToNative(this SoundEffectType effect) + { + int ret = 0; + + /* Native enum values are defined as below: + typedef enum { + SOUND_EFFECT_REFERENCE_COPY = 0x0001, //< Including reference source + SOUND_EFFECT_ACOUSTIC_ECHO_CANCEL_SPEEX = 0x0002, //< Acoustic echo cancel with speex + SOUND_EFFECT_ACOUSTIC_ECHO_CANCEL_WEBRTC = 0x0004, //< Acoustic echo cancel with webrtc + } sound_effect_method_with_reference_e; + + typedef enum { + SOUND_EFFECT_NOISE_SUPPRESSION_VOIP = 0x0001, //< Noise suppression for voice call + SOUND_EFFECT_AUTOMATIC_GAIN_CONTROL_CAPTURE = 0x0002, //< Auto Gain Control for normal capturing + } sound_effect_method_e; + */ + switch (effect) + { + case SoundEffectType.NoiseSuppression: + ret = 1; + break; + case SoundEffectType.AutoGainControl: + ret = 2; + break; + case SoundEffectType.NsWithAgc: + ret = 3; + break; + case SoundEffectType.ReferenceCopy: + ret = 1; + break; + case SoundEffectType.AecSpeex: + ret = 2; + break; + case SoundEffectType.AecWebrtc: + ret = 4; + break; + default: + Log.Error(Tag, "Invalid sound effect type."); + break; + } + + return ret; + } + + internal static SoundEffectType ToPublic(this SoundEffectNative effect) + { + SoundEffectType ret = SoundEffectType.NoiseSuppression; + + /* Native enum values are defined as below. And these can be set together. + typedef enum { + SOUND_EFFECT_NOISE_SUPPRESSION_VOIP = 0x0001, //< Noise suppression for voice call + SOUND_EFFECT_AUTOMATIC_GAIN_CONTROL_CAPTURE = 0x0002, //< Auto Gain Control for normal capturing + } sound_effect_method_e; + */ + switch (effect) + { + case SoundEffectNative.NoiseSuppression: + ret = SoundEffectType.NoiseSuppression; + break; + case SoundEffectNative.AutoGainControl: + ret = SoundEffectType.AutoGainControl; + break; + case SoundEffectNative.NoiseSuppression | SoundEffectNative.AutoGainControl: + ret = SoundEffectType.NsWithAgc; + break; + default: + Log.Error(Tag, "Invalid sound effect type."); + break; + } + + return ret; + } + + internal static SoundEffectType ToPublic(this SoundEffectWithReferenceNative effect) + { + SoundEffectType ret = SoundEffectType.ReferenceCopy; + + /* Native enum values are defined as below. And these cannot be set together. + typedef enum { + SOUND_EFFECT_REFERENCE_COPY = 0x0001, //< Including reference source + SOUND_EFFECT_ACOUSTIC_ECHO_CANCEL_SPEEX = 0x0002, //< Acoustic echo cancel with speex + SOUND_EFFECT_ACOUSTIC_ECHO_CANCEL_WEBRTC = 0x0004, //< Acoustic echo cancel with webrtc + } sound_effect_method_with_reference_e; + */ + switch (effect) + { + case SoundEffectWithReferenceNative.ReferenceCopy: + ret = SoundEffectType.ReferenceCopy; + break; + case SoundEffectWithReferenceNative.AecSpeex: + ret = SoundEffectType.AecSpeex; + break; + case SoundEffectWithReferenceNative.AecWebrtc: + ret = SoundEffectType.AecWebrtc; + break; + default: + Log.Error(Tag, "Invalid sound effect type."); + break; + } + + return ret; + } + } + +} diff --git a/src/Tizen.Multimedia/Interop/Interop.StreamPolicy.cs b/src/Tizen.Multimedia/Interop/Interop.StreamPolicy.cs index ede35629858..1c8f91b97a9 100644 --- a/src/Tizen.Multimedia/Interop/Interop.StreamPolicy.cs +++ b/src/Tizen.Multimedia/Interop/Interop.StreamPolicy.cs @@ -91,6 +91,20 @@ internal static extern AudioManagerError AddFocusStateWatchCallback(AudioStreamF [DllImport(Libraries.SoundManager, EntryPoint = "sound_manager_is_stream_on_device_by_id")] internal static extern AudioManagerError IsStreamOnDevice(AudioStreamPolicyHandle streamInfo, int deviceId, out bool isOn); + + [DllImport(Libraries.SoundManager, EntryPoint = "sound_manager_set_effect_method_with_reference_by_id")] + internal static extern AudioManagerError SetSoundEffectWithReference(AudioStreamPolicyHandle streamInfo, + SoundEffectWithReferenceNative effect, int deviceId); + + [DllImport(Libraries.SoundManager, EntryPoint = "sound_manager_get_effect_method_with_reference")] + internal static extern AudioManagerError GetSoundEffectWithReference(AudioStreamPolicyHandle streamInfo, + out SoundEffectWithReferenceNative effect, out int deviceId); + + [DllImport(Libraries.SoundManager, EntryPoint = "sound_manager_set_effect_method")] + internal static extern AudioManagerError SetSoundEffect(AudioStreamPolicyHandle streamInfo, int effect); + + [DllImport(Libraries.SoundManager, EntryPoint = "sound_manager_get_effect_method")] + internal static extern AudioManagerError GetSoundEffect(AudioStreamPolicyHandle streamInfo, out int effect); } } } \ No newline at end of file