2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 * http://www.apache.org/licenses/LICENSE-2.0
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
16 #include "ttsd_main.h"
18 #include "AudioStream.h"
23 static const char* FOCUS_SERVER_READY = "/tmp/.sound_server_ready";
26 AudioStream::AudioStream(focusReleaseCallback focusReleaseCb)
29 __focusReleaseCallback = focusReleaseCb;
30 __focusAquired = false;
32 createSoundStreamInfo();
33 createAudioHandle(TTSE_AUDIO_TYPE_RAW_S16, 16000);
36 void AudioStream::createSoundStreamInfo()
40 if (0 == access(FOCUS_SERVER_READY, F_OK)) {
41 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] focus server is available");
45 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] focus server is not available");
50 int ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_VOICE_INFORMATION, __focusStateChangedCallback, this, &__streamInfo);
51 if (SOUND_MANAGER_ERROR_NONE != ret) {
52 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to create stream info");
56 __focusAquired = false;
57 SLOG(LOG_DEBUG, tts_tag(), "[AudioStream] Create stream info");
60 AudioStream::~AudioStream()
62 __focusReleaseCallback = nullptr;
63 __focusAquired = false;
67 destroySoundStreamInfo();
70 void AudioStream::destroySoundStreamInfo()
72 int ret = sound_manager_destroy_stream_information(__streamInfo);
73 if (SOUND_MANAGER_ERROR_NONE != ret) {
74 SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to destroy stream info");
76 __streamInfo = nullptr;
77 __focusAquired = false;
80 int AudioStream::setAudioFormat(ttse_audio_type_e type, int rate)
82 if (__audioType == type && __audioRate == rate) {
83 return TTSD_ERROR_NONE;
86 SLOG(LOG_INFO, tts_tag(), "[AudioStream] Audio info is different. type:(%d)/(%d), rate:(%d)/(%d)",
87 __audioType, type, __audioRate, rate);
90 if (TTSD_ERROR_NONE != createAudioHandle(type, rate)) {
91 return TTSD_ERROR_OPERATION_FAILED;
95 const char* extra_info = __currentExtraInfo.empty() ? nullptr : __currentExtraInfo.c_str();
96 acquireSoundFocus(extra_info);
99 __state = AUDIO_STATE_READY;
100 return TTSD_ERROR_NONE;
103 int AudioStream::acquireSoundFocus(const char* extra_info)
105 if (nullptr == extra_info) {
106 __currentExtraInfo.clear();
108 __currentExtraInfo.assign(extra_info);
111 int ret = sound_manager_acquire_focus(__streamInfo, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, extra_info);
112 if (SOUND_MANAGER_ERROR_NONE != ret) {
113 SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to acquire focus");
115 SLOG(LOG_DEBUG, tts_tag(), "[AudioStream] Success to acquire focus");
118 ret = audio_out_set_sound_stream_info(__audioHandle, __streamInfo);
119 if (AUDIO_IO_ERROR_NONE != ret) {
120 SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to set stream info");
121 return TTSD_ERROR_OPERATION_FAILED;
124 __focusAquired = true;
125 return TTSD_ERROR_NONE;
128 int AudioStream::releaseSoundFocus()
130 sound_stream_focus_state_e focusState = SOUND_STREAM_FOCUS_STATE_ACQUIRED;
131 int ret = sound_manager_get_focus_state(__streamInfo, &focusState, nullptr);
132 if (SOUND_MANAGER_ERROR_NONE != ret) {
133 SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to get focus state: %d", ret);
136 if (SOUND_STREAM_FOCUS_STATE_ACQUIRED != focusState) {
137 SLOG(LOG_INFO, tts_tag(), "[AudioStream] This handle has no focus");
138 return TTSD_ERROR_NONE;
141 ret = sound_manager_release_focus(__streamInfo, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, nullptr);
142 if (SOUND_MANAGER_ERROR_NONE != ret) {
143 SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to release focus");
144 return TTSD_ERROR_OPERATION_FAILED;
147 __focusAquired = false;
148 return TTSD_ERROR_NONE;
151 int AudioStream::prepareAudioOut()
154 SLOG(LOG_DEBUG, tts_tag(), "[AudioStream] Audio is already prepared");
155 return TTSD_ERROR_NONE;
158 int ret = audio_out_prepare(__audioHandle);
159 if (AUDIO_IO_ERROR_NONE != ret) {
160 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to prepare audio : %d", ret);
161 return TTSD_ERROR_OPERATION_FAILED;
165 __state = AUDIO_STATE_PLAY;
166 return TTSD_ERROR_NONE;
169 int AudioStream::playAudioData(char* buffer, unsigned int length)
171 if (false == __prepared) {
172 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Audio is not prepared");
173 return TTSD_ERROR_OPERATION_FAILED;
176 int ret = audio_out_write(__audioHandle, static_cast<void*>(buffer), length);
178 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to audio write - %d", ret);
179 return TTSD_ERROR_OPERATION_FAILED;
182 return TTSD_ERROR_NONE;
185 int AudioStream::unprepareAudioOut()
187 if (false == __prepared) {
188 SLOG(LOG_DEBUG, tts_tag(), "[AudioStream] Audio is not prepared");
189 return TTSD_ERROR_NONE;
192 int ret = audio_out_unprepare(__audioHandle);
193 if (AUDIO_IO_ERROR_NONE != ret) {
194 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to prepare audio : %d", ret);
195 return TTSD_ERROR_OPERATION_FAILED;
199 __state = AUDIO_STATE_READY;
200 return TTSD_ERROR_NONE;
203 void AudioStream::waitForPlay()
205 __state = AUDIO_STATE_WAIT_FOR_PLAYING;
208 AudioStream::AudioState AudioStream::getState()
213 int AudioStream::createAudioHandle(ttse_audio_type_e type, int rate)
215 audio_sample_type_e sample_type;
216 if (TTSE_AUDIO_TYPE_RAW_S16 == type) {
217 sample_type = AUDIO_SAMPLE_TYPE_S16_LE;
219 sample_type = AUDIO_SAMPLE_TYPE_U8;
222 int ret = audio_out_create_new(rate, AUDIO_CHANNEL_MONO, sample_type, &__audioHandle);
223 if (AUDIO_IO_ERROR_NONE != ret) {
224 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to create audio out handle. ret(%s)", get_error_message(ret));
225 return TTSD_ERROR_OPERATION_FAILED;
230 __state = AUDIO_STATE_READY;
232 SLOG(LOG_INFO, tts_tag(), "[AudioStream] Create audio");
233 return TTSD_ERROR_NONE;
236 void AudioStream::destroyAudioHandle()
238 if (nullptr == __audioHandle) {
239 SLOG(LOG_INFO, tts_tag(), "[AudioStream] Audio handle is not exist");
243 int ret = audio_out_destroy(__audioHandle);
244 if (AUDIO_IO_ERROR_NONE != ret) {
245 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to destroy audio out handle. ret(%s)", get_error_message(ret));
247 SLOG(LOG_INFO, tts_tag(), "[AudioStream] Destroy audio");
250 __state = AUDIO_STATE_NONE;
253 void AudioStream::__focusStateChangedCallback(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask,
254 sound_stream_focus_state_e focus_state, sound_stream_focus_change_reason_e reason_for_change,
255 int sound_behavior, const char *extra_info, void *user_data)
257 SLOG(LOG_INFO, tts_tag(), "[AudioStream] focus state changed to (%d) with reason(%d) and extra info(%s)",
258 (int)focus_state, (int)reason_for_change, extra_info);
260 AudioStream* audioOut = static_cast<AudioStream*>(user_data);
261 if (stream_info != audioOut->__streamInfo) {
262 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Invalid stream info handle");
266 if (false == audioOut->__prepared || AUDIO_STATE_NONE == audioOut->__state || AUDIO_STATE_READY == audioOut->__state) {
270 if (SOUND_STREAM_FOCUS_FOR_PLAYBACK != focus_mask || SOUND_STREAM_FOCUS_STATE_RELEASED != focus_state) {
274 SLOG(LOG_INFO, tts_tag(), "[AudioStream] Focus is released on playing. Invoke callback");
275 if (audioOut->__focusReleaseCallback) {
276 audioOut->__focusReleaseCallback();