From 3d07bfbbebbae9fe8246822cc04e1c044ece5290 Mon Sep 17 00:00:00 2001 From: Suyeon Hwang <35016426+stom-hwang@users.noreply.github.com> Date: Thu, 7 Sep 2023 12:51:43 +0900 Subject: [PATCH] [Tts] Add new internal API for TTS synthesized PCM (#5526) * Add new internal method for playing mode Signed-off-by: Suyeon Hwang * Inherit System.EventArgs class Signed-off-by: Suyeon Hwang --------- Signed-off-by: Suyeon Hwang --- src/Tizen.Uix.Tts/Interop/Interop.Tts.cs | 12 ++ .../Tizen.Uix.Tts/SynthesizedPcmEventArgs.cs | 89 ++++++++++++ src/Tizen.Uix.Tts/Tizen.Uix.Tts/TtsClient.cs | 151 +++++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 src/Tizen.Uix.Tts/Tizen.Uix.Tts/SynthesizedPcmEventArgs.cs diff --git a/src/Tizen.Uix.Tts/Interop/Interop.Tts.cs b/src/Tizen.Uix.Tts/Interop/Interop.Tts.cs index a2afa16..7a904bd 100755 --- a/src/Tizen.Uix.Tts/Interop/Interop.Tts.cs +++ b/src/Tizen.Uix.Tts/Interop/Interop.Tts.cs @@ -80,6 +80,9 @@ internal static partial class Interop [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void TtsServiceStateChangedCB(IntPtr handle, ServiceState previous, ServiceState current, IntPtr userData); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void TtsSythesizedPcmCB(IntPtr handle, int uttId, SynthesizedPcmEvent pcmEvent, IntPtr pcmData, int pcmSize, AudioType audioType, int sampleRate, IntPtr userData); + [DllImport(Libraries.Tts, EntryPoint = "tts_create", CallingConvention = CallingConvention.Cdecl)] internal static extern TtsError TtsCreate(out IntPtr handle); @@ -193,5 +196,14 @@ internal static partial class Interop [DllImport(Libraries.Tts, EntryPoint = "tts_unset_service_state_changed_cb", CallingConvention = CallingConvention.Cdecl)] internal static extern TtsError TtsUnsetServiceStateChangedCB(IntPtr handle); + + [DllImport(Libraries.Tts, EntryPoint = "tts_set_playing_mode", CallingConvention = CallingConvention.Cdecl)] + internal static extern TtsError TtsSetPlayingMode(IntPtr handle, PlayingMode mode); + + [DllImport(Libraries.Tts, EntryPoint = "tts_set_synthesized_pcm_cb", CallingConvention = CallingConvention.Cdecl)] + internal static extern TtsError TtsSetSynthesizedPcmCB(IntPtr handle, TtsSythesizedPcmCB callback, IntPtr userData); + + [DllImport(Libraries.Tts, EntryPoint = "tts_unset_synthesized_pcm_cb", CallingConvention = CallingConvention.Cdecl)] + internal static extern TtsError TtsUnsetSynthesizedPcmCB(IntPtr handle); } } diff --git a/src/Tizen.Uix.Tts/Tizen.Uix.Tts/SynthesizedPcmEventArgs.cs b/src/Tizen.Uix.Tts/Tizen.Uix.Tts/SynthesizedPcmEventArgs.cs new file mode 100644 index 0000000..7751dc2 --- /dev/null +++ b/src/Tizen.Uix.Tts/Tizen.Uix.Tts/SynthesizedPcmEventArgs.cs @@ -0,0 +1,89 @@ +/* +* Copyright (c) 2023 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; +using System.ComponentModel; + +namespace Tizen.Uix.Tts +{ + /// + /// This class holds information related to the TTS SynthesizedPcm event. + /// + /// 11 + [EditorBrowsable(EditorBrowsableState.Never)] + public class SynthesizedPcmEventArgs : EventArgs + { + internal SynthesizedPcmEventArgs(int utteranceId, SynthesizedPcmEvent synthesizedPcmEvent, byte[] data, AudioType audioType, int sampleRate) + { + UtteranceId = utteranceId; + EventType = synthesizedPcmEvent; + Data = data; + AudioType = audioType; + SampleRate = sampleRate; + } + + /// + /// The utterance ID. + /// + /// 11 + public int UtteranceId + { + get; + internal set; + } + + /// + /// The event of the PCM data. + /// + /// 11 + public SynthesizedPcmEvent EventType + { + get; + internal set; + } + + /// + /// The syntehsized PCM data. + /// + /// 11 + public byte[] Data + { + get; + internal set; + } + + /// + /// The audio type of the PCM data. + /// + /// 11 + public AudioType AudioType + { + get; + internal set; + } + + /// + /// The sample rate of the PCM data. + /// + /// 11 + public int SampleRate + { + get; + internal set; + } + } +} diff --git a/src/Tizen.Uix.Tts/Tizen.Uix.Tts/TtsClient.cs b/src/Tizen.Uix.Tts/Tizen.Uix.Tts/TtsClient.cs index e5b359b..e26d071 100644 --- a/src/Tizen.Uix.Tts/Tizen.Uix.Tts/TtsClient.cs +++ b/src/Tizen.Uix.Tts/Tizen.Uix.Tts/TtsClient.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; +using System.ComponentModel; using static Interop.Tts; namespace Tizen.Uix.Tts @@ -231,6 +232,70 @@ namespace Tizen.Uix.Tts }; /// + /// Enumeration for the playing modes of TTS. + /// + /// 11 + [EditorBrowsable(EditorBrowsableState.Never)] + public enum PlayingMode + { + /// + /// Mode for TTS playing on TTS service. + /// + ByService = 0, + + /// + /// Mode for TTS playing on TTS client. + /// + ByClient = 1 + }; + + /// + /// Enumeration for the audio types. + /// + /// 11 + [EditorBrowsable(EditorBrowsableState.Never)] + public enum AudioType + { + /// + /// Signed 16-bit audio type. + /// + RawS16 = 0, + + /// + /// Unsigned 8-bit audio type. + /// + RawU8 = 1 + }; + + /// + /// Enumeration for the synthesized PCM events. + /// + /// 11 + [EditorBrowsable(EditorBrowsableState.Never)] + public enum SynthesizedPcmEvent + { + /// + /// The PCM synthesis failed. + /// + Fail = -1, + + /// + /// Received initial synthesized PCM data for an utterance. + /// + Start = 1, + + /// + /// Received synthesized PCM data, not the first and last in the stream. + /// + Continue = 2, + + /// + /// Received the final synthesized PCM data. + /// + Finish = 3 + }; + + /// /// You can use Text-To-Speech (TTS) API's to read sound data transformed by the engine from input texts. /// Applications can add input-text to queue for reading continuously and control the player that can play, pause, and stop sound data synthesized from text. /// @@ -246,6 +311,7 @@ namespace Tizen.Uix.Tts private event EventHandler _engineChanged; private event EventHandler _screenReaderChanged; private event EventHandler _serviceStateChanged; + private EventHandler _synthesizedPcmEventHandler; private bool disposedValue = false; private readonly Object _stateChangedLock = new Object(); private readonly Object _utteranceStartedLock = new Object(); @@ -255,6 +321,7 @@ namespace Tizen.Uix.Tts private readonly Object _engineChangedLock = new Object(); private readonly Object _screenReaderChangedLock = new Object(); private readonly Object _serviceStateChangedLock = new Object(); + private readonly object _synthesizedPcmLock = new object(); private TtsStateChangedCB _stateDelegate; private TtsUtteranceStartedCB _utteranceStartedResultDelegate; private TtsUtteranceCompletedCB _utteranceCompletedResultDelegate; @@ -263,7 +330,9 @@ namespace Tizen.Uix.Tts private TtsEngineChangedCB _engineDelegate; private TtsScreenReaderChangedCB _screenReaderDelegate; private TtsServiceStateChangedCB _serviceStateDelegate; + private TtsSythesizedPcmCB _synthesizedPcmDelegate; private TtsSupportedVoiceCB _supportedvoiceDelegate; + private PlayingMode _playingMode = PlayingMode.ByService; /// /// Constructor to create a TTS instance. @@ -665,6 +734,54 @@ namespace Tizen.Uix.Tts } /// + /// Event to be invoked when the synthesized pcm data comes from the engine. + /// + /// 11 + [EditorBrowsable(EditorBrowsableState.Never)] + public event EventHandler SynthesizedPcm + { + add + { + lock (_synthesizedPcmLock) + { + if (_synthesizedPcmEventHandler == null) + { + _synthesizedPcmDelegate = (IntPtr handle, int uttId, SynthesizedPcmEvent pcmEvent, IntPtr pcmData, int pcmSize, AudioType audioType, int sampleRate, IntPtr userData) => + { + var managedPcmData = new byte[pcmSize]; + Marshal.Copy(pcmData, managedPcmData, 0, pcmSize); + SynthesizedPcmEventArgs args = new SynthesizedPcmEventArgs(uttId, pcmEvent, managedPcmData, audioType, sampleRate); + _synthesizedPcmEventHandler?.Invoke(this, args); + }; + + TtsError error = TtsSetSynthesizedPcmCB(_handle, _synthesizedPcmDelegate, IntPtr.Zero); + if (error != TtsError.None) + { + Log.Error(LogTag, "Add SynthesizedPcm Failed with error " + error); + } + } + _synthesizedPcmEventHandler += value; + } + } + + remove + { + lock (_synthesizedPcmLock) + { + _synthesizedPcmEventHandler -= value; + if (_synthesizedPcmEventHandler == null) + { + TtsError error = TtsUnsetSynthesizedPcmCB(_handle); + if (error != TtsError.None) + { + Log.Error(LogTag, "Remove SynthesizedPcm Failed with error " + error); + } + } + } + } + } + + /// /// Gets the default voice set by the user. /// /// 3 @@ -849,6 +966,40 @@ namespace Tizen.Uix.Tts } /// + /// Sets the current playing mode. + /// + /// 11 + /// + /// The current playing mode. + /// + /// + /// http://tizen.org/feature/speech.synthesis + /// + /// This exception can be due to an invalid state. + /// This exception can be due to TTS not supported. + ///
+        /// If you want to set, the Client must be in the  state.
+        /// 
+ [EditorBrowsable(EditorBrowsableState.Never)] + public PlayingMode PlayingMode + { + get + { + return _playingMode; + } + set + { + TtsError error = TtsSetPlayingMode(_handle, value); + if (error != TtsError.None) + { + Log.Error(LogTag, "Set Mode Failed with error " + error); + throw ExceptionFactory.CreateException(error); + } + _playingMode = value; + } + } + + /// /// Sets the application credential. /// /// 3 -- 2.7.4