Initial audio hal for emulator
[platform/adaptation/emulator/audio-hal-emul.git] / tizen-audio.c
1 /*
2  * audio-hal
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include "tizen-audio-internal.h"
25
26 /* audio latency */
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";
31
32 audio_return_t audio_set_message_cb(void *audio_handle, message_cb callback, void *user_data)
33 {
34     audio_return_t ret = AUDIO_RET_OK;
35
36     AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
37     AUDIO_RETURN_VAL_IF_FAIL(callback, AUDIO_ERR_PARAMETER);
38
39     ret = _audio_comm_set_message_callback((audio_hal_t *)audio_handle, callback, user_data);
40
41     return ret;
42 }
43
44 audio_return_t audio_init(void **audio_handle)
45 {
46     audio_hal_t *ah;
47     audio_return_t ret = AUDIO_RET_OK;
48
49     AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
50
51     if (!(ah = malloc(sizeof(audio_hal_t)))) {
52         AUDIO_LOG_ERROR("am malloc failed");
53         return AUDIO_ERR_RESOURCE;
54     }
55     if (AUDIO_IS_ERROR((ret = _audio_device_init(ah)))) {
56         AUDIO_LOG_ERROR("device init failed");
57         goto error_exit;
58     }
59     if (AUDIO_IS_ERROR((ret = _audio_volume_init(ah)))) {
60         AUDIO_LOG_ERROR("stream init failed");
61         goto error_exit;
62     }
63     if (AUDIO_IS_ERROR((ret = _audio_util_init(ah)))) {
64         AUDIO_LOG_ERROR("util init failed");
65         goto error_exit;
66     }
67     if (AUDIO_IS_ERROR((ret = _audio_comm_init(ah)))) {
68         AUDIO_LOG_ERROR("comm init failed");
69         goto error_exit;
70     }
71
72     *audio_handle = (void *)ah;
73     return AUDIO_RET_OK;
74
75 error_exit:
76     if (ah)
77         free(ah);
78
79     return ret;
80 }
81
82 audio_return_t audio_deinit(void *audio_handle)
83 {
84     audio_hal_t *ah = (audio_hal_t *)audio_handle;
85
86     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
87
88     _audio_device_deinit(ah);
89     _audio_volume_deinit(ah);
90     _audio_util_deinit(ah);
91     _audio_comm_deinit(ah);
92     free(ah);
93     ah = NULL;
94
95     return AUDIO_RET_OK;
96 }
97
98 /* Latency msec */
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;
105
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
120 };
121
122 int _sample_spec_valid(uint32_t rate, audio_sample_format_t format, uint32_t channels)
123 {
124     if ((rate <= 0                 ||
125         rate > (48000U*4U)         ||
126         channels <= 0              ||
127         channels > 32U             ||
128         format >= AUDIO_SAMPLE_MAX ||
129         format <  AUDIO_SAMPLE_U8))
130         return 0;
131
132     AUDIO_LOG_ERROR("hal-latency - _sample_spec_valid() -> return true");
133
134     return 1;
135 }
136
137 uint32_t _audio_usec_to_bytes(uint64_t t, uint32_t rate, audio_sample_format_t format, uint32_t channels)
138 {
139     uint32_t ret = (uint32_t) (((t * rate) / 1000000ULL)) * (g_size_table[format] * channels);
140     AUDIO_LOG_DEBUG("hal-latency - return %d", ret);
141     return ret;
142 }
143
144 uint32_t _audio_sample_size(audio_sample_format_t format)
145 {
146     return g_size_table[format];
147 }
148 audio_return_t audio_get_buffer_attr(void                  *audio_handle,
149                                      uint32_t              direction,
150                                      const char            *latency,
151                                      uint32_t              samplerate,
152                                      audio_sample_format_t format,
153                                      uint32_t              channels,
154                                      uint32_t              *maxlength,
155                                      uint32_t              *tlength,
156                                      uint32_t              *prebuf,
157                                      uint32_t              *minreq,
158                                      uint32_t              *fragsize)
159 {
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);
167
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);
169
170     uint32_t period_time        = 0,
171              sample_per_period  = 0;
172
173     if (_sample_spec_valid(samplerate, format, channels) == 0) {
174         return AUDIO_ERR_PARAMETER;
175     }
176
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;
182             *prebuf            = 0;
183             *minreq            = -1;
184             *tlength           = -1;
185             *maxlength         = -1;
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;
191             *prebuf            = 0;
192             *minreq            = -1;
193             *tlength           = -1;
194             *maxlength         = -1;
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;
200             *prebuf            = 0;
201             *minreq            = -1;
202             *tlength           = -1;
203             *maxlength         = -1;
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;
209             *prebuf            = 0;
210             *minreq            = -1;
211             *tlength           = -1;
212             *maxlength         = -1;
213             *fragsize          = sample_per_period * _audio_sample_size(format);
214         } else {
215             AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
216             return AUDIO_ERR_UNDEFINED;
217         }
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;
223             *prebuf            = 0;
224             *minreq            = -1;
225             *tlength           = (samplerate / 10) * _audio_sample_size(format) * channels;  /* 100ms */
226             *maxlength         = -1;
227             *fragsize          = 0;
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;
232             *prebuf            = 0;
233             *minreq            = -1;
234             *tlength           = (uint32_t) _audio_usec_to_bytes(200000, samplerate, format, channels);
235             *maxlength         = -1;
236             *fragsize          = -1;
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;
241             *prebuf            = 0;
242             *minreq            = -1;
243             *tlength           = (uint32_t) _audio_usec_to_bytes(400000, samplerate, format, channels);
244             *maxlength         = -1;
245             *fragsize          = -1;
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;
250             *prebuf            = 0;
251             *minreq            = _audio_usec_to_bytes(20000, samplerate, format, channels);
252             *tlength           = _audio_usec_to_bytes(100000, samplerate, format, channels);
253             *maxlength         = -1;
254             *fragsize          = 0;
255         } else {
256             AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
257             return AUDIO_ERR_UNDEFINED;
258         }
259     }
260
261     AUDIO_LOG_INFO("hal-latency - return attr --> prebuf:%d, minreq:%d, tlength:%d, maxlength:%d, fragsize:%d", *prebuf, *minreq, *tlength, *maxlength, *fragsize);
262     return AUDIO_RET_OK;
263 }