4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include "tizen-audio-internal.h"
27 static const char* AUDIO_LATENCY_LOW = "low";
28 static const char* AUDIO_LATENCY_MID = "mid";
29 static const char* AUDIO_LATENCY_HIGH = "high";
30 static const char* AUDIO_LATENCY_VOIP = "voip";
32 audio_return_t audio_set_message_cb(void *audio_handle, message_cb callback, void *user_data)
34 audio_return_t ret = AUDIO_RET_OK;
36 AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
37 AUDIO_RETURN_VAL_IF_FAIL(callback, AUDIO_ERR_PARAMETER);
39 ret = _audio_comm_set_message_callback((audio_hal_t *)audio_handle, callback, user_data);
44 audio_return_t audio_init(void **audio_handle)
47 audio_return_t ret = AUDIO_RET_OK;
49 AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
51 if (!(ah = malloc(sizeof(audio_hal_t)))) {
52 AUDIO_LOG_ERROR("am malloc failed");
53 return AUDIO_ERR_RESOURCE;
55 if (AUDIO_IS_ERROR((ret = _audio_device_init(ah)))) {
56 AUDIO_LOG_ERROR("device init failed");
59 if (AUDIO_IS_ERROR((ret = _audio_volume_init(ah)))) {
60 AUDIO_LOG_ERROR("stream init failed");
63 if (AUDIO_IS_ERROR((ret = _audio_util_init(ah)))) {
64 AUDIO_LOG_ERROR("util init failed");
67 if (AUDIO_IS_ERROR((ret = _audio_comm_init(ah)))) {
68 AUDIO_LOG_ERROR("comm init failed");
72 *audio_handle = (void *)ah;
82 audio_return_t audio_deinit(void *audio_handle)
84 audio_hal_t *ah = (audio_hal_t *)audio_handle;
86 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
88 _audio_device_deinit(ah);
89 _audio_volume_deinit(ah);
90 _audio_util_deinit(ah);
91 _audio_comm_deinit(ah);
99 static const unsigned int PERIOD_TIME_FOR_ULOW_LATENCY_MSEC = 20;
100 static const unsigned int PERIOD_TIME_FOR_LOW_LATENCY_MSEC = 25;
101 static const unsigned int PERIOD_TIME_FOR_MID_LATENCY_MSEC = 50;
102 static const unsigned int PERIOD_TIME_FOR_HIGH_LATENCY_MSEC = 75;
103 static const unsigned int PERIOD_TIME_FOR_UHIGH_LATENCY_MSEC = 150;
104 static const unsigned int PERIOD_TIME_FOR_VOIP_LATENCY_MSEC = 20;
106 static const uint32_t g_size_table[] = {
107 [AUDIO_SAMPLE_U8] = 1,
108 [AUDIO_SAMPLE_ULAW] = 1,
109 [AUDIO_SAMPLE_ALAW] = 1,
110 [AUDIO_SAMPLE_S16LE] = 2,
111 [AUDIO_SAMPLE_S16BE] = 2,
112 [AUDIO_SAMPLE_FLOAT32LE] = 4,
113 [AUDIO_SAMPLE_FLOAT32BE] = 4,
114 [AUDIO_SAMPLE_S32LE] = 4,
115 [AUDIO_SAMPLE_S32BE] = 4,
116 [AUDIO_SAMPLE_S24LE] = 3,
117 [AUDIO_SAMPLE_S24BE] = 3,
118 [AUDIO_SAMPLE_S24_32LE] = 4,
119 [AUDIO_SAMPLE_S24_32BE] = 4
122 int _sample_spec_valid(uint32_t rate, audio_sample_format_t format, uint32_t channels)
125 rate > (48000U*4U) ||
128 format >= AUDIO_SAMPLE_MAX ||
129 format < AUDIO_SAMPLE_U8))
132 AUDIO_LOG_ERROR("hal-latency - _sample_spec_valid() -> return true");
137 uint32_t _audio_usec_to_bytes(uint64_t t, uint32_t rate, audio_sample_format_t format, uint32_t channels)
139 uint32_t ret = (uint32_t) (((t * rate) / 1000000ULL)) * (g_size_table[format] * channels);
140 AUDIO_LOG_DEBUG("hal-latency - return %d", ret);
144 uint32_t _audio_sample_size(audio_sample_format_t format)
146 return g_size_table[format];
148 audio_return_t audio_get_buffer_attr(void *audio_handle,
152 audio_sample_format_t format,
160 AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
161 AUDIO_RETURN_VAL_IF_FAIL(latency, AUDIO_ERR_PARAMETER);
162 AUDIO_RETURN_VAL_IF_FAIL(maxlength, AUDIO_ERR_PARAMETER);
163 AUDIO_RETURN_VAL_IF_FAIL(tlength, AUDIO_ERR_PARAMETER);
164 AUDIO_RETURN_VAL_IF_FAIL(prebuf, AUDIO_ERR_PARAMETER);
165 AUDIO_RETURN_VAL_IF_FAIL(minreq, AUDIO_ERR_PARAMETER);
166 AUDIO_RETURN_VAL_IF_FAIL(fragsize, AUDIO_ERR_PARAMETER);
168 AUDIO_LOG_DEBUG("hal-latency - audio_get_buffer_attr(direction:%d, latency:%s, samplerate:%d, format:%d, channels:%d)", direction, latency, samplerate, format, channels);
170 uint32_t period_time = 0,
171 sample_per_period = 0;
173 if (_sample_spec_valid(samplerate, format, channels) == 0) {
174 return AUDIO_ERR_PARAMETER;
177 if (direction == AUDIO_DIRECTION_IN) {
178 if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
179 AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_LOW");
180 period_time = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
181 sample_per_period = (samplerate * period_time) / 1000;
186 *fragsize = sample_per_period * _audio_sample_size(format);
187 } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
188 AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_MID");
189 period_time = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
190 sample_per_period = (samplerate * period_time) / 1000;
195 *fragsize = sample_per_period * _audio_sample_size(format);
196 } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
197 AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_HIGH");
198 period_time = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
199 sample_per_period = (samplerate * period_time) / 1000;
204 *fragsize = sample_per_period * _audio_sample_size(format);
205 } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
206 AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_VOIP");
207 period_time = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
208 sample_per_period = (samplerate * period_time) / 1000;
213 *fragsize = sample_per_period * _audio_sample_size(format);
215 AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
216 return AUDIO_ERR_UNDEFINED;
218 } else { /* AUDIO_DIRECTION_OUT */
219 if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
220 AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_LOW");
221 period_time = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
222 sample_per_period = (samplerate * period_time) / 1000;
225 *tlength = (samplerate / 10) * _audio_sample_size(format) * channels; /* 100ms */
228 } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
229 AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_MID");
230 period_time = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
231 sample_per_period = (samplerate * period_time) / 1000;
234 *tlength = (uint32_t) _audio_usec_to_bytes(200000, samplerate, format, channels);
237 } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
238 AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_HIGH");
239 period_time = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
240 sample_per_period = (samplerate * period_time) / 1000;
243 *tlength = (uint32_t) _audio_usec_to_bytes(400000, samplerate, format, channels);
246 } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
247 AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_VOIP");
248 period_time = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
249 sample_per_period = (samplerate * period_time) / 1000;
251 *minreq = _audio_usec_to_bytes(20000, samplerate, format, channels);
252 *tlength = _audio_usec_to_bytes(100000, samplerate, format, channels);
256 AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
257 return AUDIO_ERR_UNDEFINED;
261 AUDIO_LOG_INFO("hal-latency - return attr --> prebuf:%d, minreq:%d, tlength:%d, maxlength:%d, fragsize:%d", *prebuf, *minreq, *tlength, *maxlength, *fragsize);