cad42844ddc42d9188d0f8b170080ffa7cb8a061
[platform/adaptation/spreadtrum/audio-hal-sc7727.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_init (void **audio_handle)
33 {
34     audio_hal_t *ah;
35     audio_return_t ret = AUDIO_RET_OK;
36
37     AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
38
39     if (!(ah = malloc(sizeof(audio_hal_t)))) {
40         AUDIO_LOG_ERROR("am malloc failed");
41         return AUDIO_ERR_RESOURCE;
42     }
43     if (AUDIO_IS_ERROR((ret = _audio_device_init(ah)))) {
44         AUDIO_LOG_ERROR("device init failed");
45         goto error_exit;
46     }
47     if (AUDIO_IS_ERROR((ret = _audio_volume_init(ah)))) {
48         AUDIO_LOG_ERROR("stream init failed");
49         goto error_exit;
50     }
51     if (AUDIO_IS_ERROR((ret = _audio_ucm_init(ah)))) {
52         AUDIO_LOG_ERROR("ucm init failed");
53         goto error_exit;
54     }
55     if (AUDIO_IS_ERROR((ret = _audio_util_init(ah)))) {
56         AUDIO_LOG_ERROR("mixer init failed");
57         goto error_exit;
58     }
59
60     *audio_handle = (void *)ah;
61     return AUDIO_RET_OK;
62
63 error_exit:
64     if (ah)
65         free(ah);
66
67     return ret;
68 }
69
70 audio_return_t audio_deinit (void *audio_handle)
71 {
72     audio_hal_t *ah = (audio_hal_t *)audio_handle;
73
74     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
75
76     _audio_device_deinit(ah);
77     _audio_volume_deinit(ah);
78     _audio_ucm_deinit(ah);
79     _audio_util_deinit(ah);
80     free(ah);
81     ah = NULL;
82
83     return AUDIO_RET_OK;
84 }
85
86 /* Latency msec */
87 static const unsigned int PERIOD_TIME_FOR_ULOW_LATENCY_MSEC  = 20;
88 static const unsigned int PERIOD_TIME_FOR_LOW_LATENCY_MSEC   = 25;
89 static const unsigned int PERIOD_TIME_FOR_MID_LATENCY_MSEC   = 50;
90 static const unsigned int PERIOD_TIME_FOR_HIGH_LATENCY_MSEC  = 75;
91 static const unsigned int PERIOD_TIME_FOR_UHIGH_LATENCY_MSEC = 150;
92 static const unsigned int PERIOD_TIME_FOR_VOIP_LATENCY_MSEC  = 20;
93
94 static const uint32_t g_size_table[] = {
95     [AUDIO_SAMPLE_U8]        = 1,
96     [AUDIO_SAMPLE_ULAW]      = 1,
97     [AUDIO_SAMPLE_ALAW]      = 1,
98     [AUDIO_SAMPLE_S16LE]     = 2,
99     [AUDIO_SAMPLE_S16BE]     = 2,
100     [AUDIO_SAMPLE_FLOAT32LE] = 4,
101     [AUDIO_SAMPLE_FLOAT32BE] = 4,
102     [AUDIO_SAMPLE_S32LE]     = 4,
103     [AUDIO_SAMPLE_S32BE]     = 4,
104     [AUDIO_SAMPLE_S24LE]     = 3,
105     [AUDIO_SAMPLE_S24BE]     = 3,
106     [AUDIO_SAMPLE_S24_32LE]  = 4,
107     [AUDIO_SAMPLE_S24_32BE]  = 4
108 };
109
110 int _sample_spec_valid(uint32_t rate, audio_sample_format_t format, uint32_t channels)
111 {
112     if ((rate <= 0                 ||
113         rate > (48000U*4U)         ||
114         channels <= 0              ||
115         channels > 32U             ||
116         format >= AUDIO_SAMPLE_MAX ||
117         format <  AUDIO_SAMPLE_U8))
118         return 0;
119
120     AUDIO_LOG_ERROR("hal-latency - _sample_spec_valid() -> return true");
121
122     return 1;
123 }
124
125 uint32_t _audio_usec_to_bytes(uint64_t t, uint32_t rate, audio_sample_format_t format, uint32_t channels)
126 {
127     uint32_t ret = (uint32_t) (((t * rate) / 1000000ULL)) * (g_size_table[format] * channels);
128     AUDIO_LOG_DEBUG("hal-latency - return %d", ret);
129     return ret;
130 }
131
132 uint32_t _audio_sample_size(audio_sample_format_t format)
133 {
134     return g_size_table[format];
135 }
136 audio_return_t audio_get_buffer_attr(void                  *audio_handle,
137                                      uint32_t              direction,
138                                      const char            *latency,
139                                      uint32_t              samplerate,
140                                      audio_sample_format_t format,
141                                      uint32_t              channels,
142                                      uint32_t              *maxlength,
143                                      uint32_t              *tlength,
144                                      uint32_t              *prebuf,
145                                      uint32_t              *minreq,
146                                      uint32_t              *fragsize)
147 {
148     AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
149     AUDIO_RETURN_VAL_IF_FAIL(latency, AUDIO_ERR_PARAMETER);
150     AUDIO_RETURN_VAL_IF_FAIL(maxlength, AUDIO_ERR_PARAMETER);
151     AUDIO_RETURN_VAL_IF_FAIL(tlength, AUDIO_ERR_PARAMETER);
152     AUDIO_RETURN_VAL_IF_FAIL(prebuf, AUDIO_ERR_PARAMETER);
153     AUDIO_RETURN_VAL_IF_FAIL(minreq, AUDIO_ERR_PARAMETER);
154     AUDIO_RETURN_VAL_IF_FAIL(fragsize, AUDIO_ERR_PARAMETER);
155
156     AUDIO_LOG_DEBUG("hal-latency - audio_get_buffer_attr(direction:%d, latency:%s, samplerate:%d, format:%d, channels:%d)", direction, latency, samplerate, format, channels);
157
158     uint32_t period_time        = 0,
159              sample_per_period  = 0;
160
161     if (_sample_spec_valid(samplerate, format, channels) == 0) {
162         return AUDIO_ERR_PARAMETER;
163     }
164
165     if (direction == AUDIO_DIRECTION_IN) {
166         if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
167             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_LOW");
168             period_time        = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
169             sample_per_period  = (samplerate * period_time) / 1000;
170             *prebuf            = 0;
171             *minreq            = -1;
172             *tlength           = -1;
173             *maxlength         = -1;
174             *fragsize          = sample_per_period * _audio_sample_size(format);
175         } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
176             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_MID");
177             period_time        = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
178             sample_per_period  = (samplerate * period_time) / 1000;
179             *prebuf            = 0;
180             *minreq            = -1;
181             *tlength           = -1;
182             *maxlength         = -1;
183             *fragsize          = sample_per_period * _audio_sample_size(format);
184         } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
185             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_HIGH");
186             period_time        = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
187             sample_per_period  = (samplerate * period_time) / 1000;
188             *prebuf            = 0;
189             *minreq            = -1;
190             *tlength           = -1;
191             *maxlength         = -1;
192             *fragsize          = sample_per_period * _audio_sample_size(format);
193         } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
194             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_VOIP");
195             period_time        = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
196             sample_per_period  = (samplerate * period_time) / 1000;
197             *prebuf            = 0;
198             *minreq            = -1;
199             *tlength           = -1;
200             *maxlength         = -1;
201             *fragsize          = sample_per_period * _audio_sample_size(format);
202         } else {
203             AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
204             return AUDIO_ERR_UNDEFINED;
205         }
206     } else {  /* AUDIO_DIRECTION_OUT */
207         if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
208             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_LOW");
209             period_time        = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
210             sample_per_period  = (samplerate * period_time) / 1000;
211             *prebuf            = 0;
212             *minreq            = -1;
213             *tlength           = (samplerate / 10) * _audio_sample_size(format) * channels;  /* 100ms */
214             *maxlength         = -1;
215             *fragsize          = 0;
216         } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
217             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_MID");
218             period_time        = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
219             sample_per_period  = (samplerate * period_time) / 1000;
220             *prebuf            = 0;
221             *minreq            = -1;
222             *tlength           = (uint32_t) _audio_usec_to_bytes(200000, samplerate, format, channels);
223             *maxlength         = -1;
224             *fragsize          = -1;
225         } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
226             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_HIGH");
227             period_time        = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
228             sample_per_period  = (samplerate * period_time) / 1000;
229             *prebuf            = 0;
230             *minreq            = -1;
231             *tlength           = (uint32_t) _audio_usec_to_bytes(400000, samplerate, format, channels);
232             *maxlength         = -1;
233             *fragsize          = -1;
234         } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
235             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_VOIP");
236             period_time        = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
237             sample_per_period  = (samplerate * period_time) / 1000;
238             *prebuf            = 0;
239             *minreq            = _audio_usec_to_bytes(20000, samplerate, format, channels);
240             *tlength           = _audio_usec_to_bytes(100000, samplerate, format, channels);
241             *maxlength         = -1;
242             *fragsize          = 0;
243         } else {
244             AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
245             return AUDIO_ERR_UNDEFINED;
246         }
247     }
248
249     AUDIO_LOG_INFO("hal-latency - return attr --> prebuf:%d, minreq:%d, tlength:%d, maxlength:%d, fragsize:%d", *prebuf, *minreq, *tlength, *maxlength, *fragsize);
250     return AUDIO_RET_OK;
251 }