2 * Copyright(c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 using Tizen.Multimedia;
23 using static Tizen.AIAvatar.AIAvatar;
25 namespace Tizen.AIAvatar
27 internal class AudioRecorder
29 private const string privilegeForRecording = "http://tizen.org/privilege/recorder";
31 private AsyncAudioCapture asyncAudioCapture;
33 private byte[] recordedBuffer;
34 private float desiredBufferDuration = 0.16f;
35 private int desiredBufferLength;
37 private Timer audioRecordingTimer;
39 private Action audioRecdingAction;
40 private Action<byte[],int > bufferAction;
42 private static AudioRecorder instance;
44 internal static AudioRecorder Instance
50 instance = new AudioRecorder();
56 internal event EventHandler<RecordBufferChangedEventArgs> BufferChanged;
58 internal AudioRecorder()
60 Utils.CheckPrivilege(privilegeForRecording);
61 desiredBufferLength = (int)(CurrentAudioOptions.SampleRate * desiredBufferDuration * 2);
65 internal void InitMic(BlendShapePlayer animator, uint recordingTime = 160)
67 audioRecordingTimer = new Timer(recordingTime);
70 //TODO : Connection MIC
71 var lipSyncer = (animator.GetAnimationModule(AnimationModuleType.LipSyncer) as LipSyncer);
74 Tizen.Log.Error(LogTag, "LipSyncer of animator is null");
77 this.audioRecdingAction = lipSyncer.OnRecodingTick;
78 this.bufferAction = lipSyncer.OnRecordBufferChanged;
80 BufferChanged += OnRecordBufferChanged;
81 audioRecordingTimer.Tick += AudioRecordingTimerTick;
86 internal void DeinitMic()
89 BufferChanged -= OnRecordBufferChanged;
91 if (audioRecordingTimer != null)
93 audioRecordingTimer.Stop();
94 audioRecordingTimer.Tick -= AudioRecordingTimerTick;
96 audioRecordingTimer.Dispose();
97 audioRecordingTimer = null;
99 audioRecdingAction = null;
102 internal void StartRecording()
104 audioRecordingTimer?.Start();
105 asyncAudioCapture = new AsyncAudioCapture(CurrentAudioOptions.SampleRate, CurrentAudioOptions.Channel, CurrentAudioOptions.SampleType);
107 recordedBuffer = new byte[0];
108 asyncAudioCapture.DataAvailable += (s, e) =>
110 recordedBuffer = recordedBuffer.Concat(e.Data).ToArray();
111 if (recordedBuffer.Length >= desiredBufferLength)
113 var recordedBuffer = this.recordedBuffer;
114 this.recordedBuffer = Array.Empty<byte>();
116 BufferChanged?.Invoke(this, new RecordBufferChangedEventArgs(recordedBuffer, CurrentAudioOptions.SampleRate));
119 asyncAudioCapture.Prepare();
120 Log.Info(LogTag, "Start Recording - Preapre AsyncAudioCapture");
123 internal void StopRecording()
125 audioRecordingTimer?.Stop();
126 asyncAudioCapture.Dispose();
129 internal void PauseRecording()
131 asyncAudioCapture.Pause();
134 internal void ResumeRecording()
136 asyncAudioCapture.Resume();
139 private void OnRecordBufferChanged(object sender, RecordBufferChangedEventArgs e)
141 bufferAction?.Invoke(e.RecordedBuffer, CurrentAudioOptions.SampleRate);
144 private bool AudioRecordingTimerTick(object source, Timer.TickEventArgs e)
146 Log.Info(LogTag, "TickTimer");
147 audioRecdingAction?.Invoke();