Release version 0.1.41
[platform/core/uifw/stt.git] / server / sttd_recorder.c
1 /*
2 *  Copyright (c) 2012, 2013 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.
12 */
13
14 #include <audio_io.h> 
15 #include <Ecore.h>
16 #include <math.h>
17 #include "sttd_recorder.h"
18 #include "sttd_main.h"
19 #include "stt_defs.h"
20
21
22 #define FRAME_LENGTH 160
23 #define BUFFER_LENGTH FRAME_LENGTH * 2
24
25 static stt_recorder_audio_cb    g_audio_cb;
26 static audio_in_h               g_audio_in_h;
27
28 static sttd_recorder_state      g_recorder_state = -1;
29
30 static sttp_audio_type_e        g_audio_type;
31
32 static char g_buffer[BUFFER_LENGTH];
33
34 static FILE* g_pFile_vol;
35
36 static char g_temp_vol[64];
37
38 /* Sound buf save */
39 /*
40 #define BUF_SAVE_MODE
41 */
42
43 #ifdef BUF_SAVE_MODE
44 static char g_temp_file_name[128] = {'\0',};
45
46 static FILE* g_pFile;
47
48 static int g_count = 1;
49 #endif 
50
51 int sttd_recorder_create(stt_recorder_audio_cb callback, sttp_audio_type_e type, int channel, unsigned int sample_rate)
52 {
53         if (NULL == callback) {
54                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Input param is NOT valid");
55                 return STTD_ERROR_INVALID_PARAMETER;
56         }
57
58         audio_channel_e audio_ch;
59         audio_sample_type_e audio_type;
60
61         switch(channel) {
62                 case 1: audio_ch = AUDIO_CHANNEL_MONO;          break;
63                 case 2: audio_ch = AUDIO_CHANNEL_STEREO;        break;
64                 default:
65                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Input channel is not supported");
66                         return STTD_ERROR_OPERATION_FAILED;
67                         break;
68         }
69
70         switch (type) {
71                 case STTP_AUDIO_TYPE_PCM_S16_LE:        audio_type = AUDIO_SAMPLE_TYPE_S16_LE;  break;
72                 case STTP_AUDIO_TYPE_PCM_U8:            audio_type = AUDIO_SAMPLE_TYPE_U8;      break;
73                 default:        
74                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Invalid Audio Type"); 
75                         return STTD_ERROR_OPERATION_FAILED;
76                         break;
77         }
78
79         int ret;
80         ret = audio_in_create(sample_rate, audio_ch, audio_type, &g_audio_in_h);
81         if (AUDIO_IO_ERROR_NONE != ret) {
82                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to create audio handle : %d", ret);
83                 return STTD_ERROR_OPERATION_FAILED;
84         }
85
86         g_audio_cb = callback;
87         g_recorder_state = STTD_RECORDER_STATE_READY;
88         g_audio_type = type;
89
90         return 0;
91 }
92
93 int sttd_recorder_destroy()
94 {
95         int ret;
96         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state) {
97                 ret = audio_in_unprepare(g_audio_in_h);
98                 if (AUDIO_IO_ERROR_NONE != ret) {
99                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to unprepare audio_in");
100                 }
101         }
102
103         ret = audio_in_destroy(g_audio_in_h);
104         if (AUDIO_IO_ERROR_NONE != ret) {
105                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to destroy audio_in");
106         }
107
108         g_audio_cb = NULL;
109         g_recorder_state = -1;
110
111         if (0 == access(STT_AUDIO_VOLUME_PATH, R_OK)) {
112                 if (0 == remove(STT_AUDIO_VOLUME_PATH)) {
113                         SLOG(LOG_WARN, TAG_STTD, "[Recorder WARN] Fail to remove volume file"); 
114                 }
115         }
116
117         return 0;
118 }
119
120 static float get_volume_decibel(char* data, int size, sttp_audio_type_e type)
121 {
122         #define MAX_AMPLITUDE_MEAN_16 23170.115738161934
123         #define MAX_AMPLITUDE_MEAN_08    89.803909382810
124
125         int i, depthByte;
126         int count = 0;
127
128         short* pcm16 = 0;
129         char* pcm8 = 0;
130
131         float db = 0.0;
132         float rms = 0.0;
133         unsigned long long square_sum = 0;
134
135         if (type == STTP_AUDIO_TYPE_PCM_S16_LE)
136                 depthByte = 2;
137         else
138                 depthByte = 1;
139
140         for (i = 0; i < size; i += (depthByte<<1)) {
141                 if (depthByte == 2) {
142                         pcm16 = (short*)(data + i);
143                         square_sum += (*pcm16) * (*pcm16);
144                 } else {
145                         pcm8 = (char*)(data +i);
146                         square_sum += (*pcm8) * (*pcm8);
147                 }
148                 count++;
149         }
150
151         rms = sqrt(square_sum/count);
152
153         if (depthByte == 2)
154                 db = 20 * log10(rms/MAX_AMPLITUDE_MEAN_16);
155         else
156                 db = 20 * log10(rms/MAX_AMPLITUDE_MEAN_08);
157
158         return db;
159 }
160
161 Eina_Bool __read_audio_func(void *data)
162 {
163         int read_byte = -1;
164
165         if (STTD_RECORDER_STATE_READY == g_recorder_state) {
166                 SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Exit audio reading func");
167                 return EINA_FALSE;
168         }
169
170         read_byte = audio_in_read(g_audio_in_h, g_buffer, BUFFER_LENGTH);
171         if (0 > read_byte) {
172                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Fail to read audio : %d", read_byte);
173                 g_recorder_state = STTD_RECORDER_STATE_READY;
174                 return EINA_FALSE;
175         }
176
177         if (0 != g_audio_cb(g_buffer, read_byte)) {
178                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Fail audio callback");
179                 sttd_recorder_stop();
180                 return EINA_FALSE;
181         }
182
183         float vol_db = get_volume_decibel(g_buffer, BUFFER_LENGTH, g_audio_type);
184
185         rewind(g_pFile_vol);
186         fwrite((void*)(&vol_db), sizeof(vol_db), 1, g_pFile_vol);
187
188 #ifdef BUF_SAVE_MODE
189         /* write pcm buffer */
190         fwrite(g_buffer, 1, BUFFER_LENGTH, g_pFile);
191 #endif
192
193         return EINA_TRUE;
194 }
195
196 int sttd_recorder_start()
197 {
198         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state)
199                 return 0;
200
201         int ret = -1; 
202         ret = audio_in_prepare(g_audio_in_h);
203         if (AUDIO_IO_ERROR_NONE != ret) {
204                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to prepare audio in : %d", ret);
205                 return STTD_ERROR_OPERATION_FAILED;
206         }
207
208         /* Add ecore timer to read audio data */
209         ecore_timer_add(0, __read_audio_func, NULL);
210
211         g_recorder_state = STTD_RECORDER_STATE_RECORDING;
212
213         g_pFile_vol = fopen(STT_AUDIO_VOLUME_PATH, "wb+");
214         if (!g_pFile_vol) {
215                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to create Volume File");
216                 return -1;
217         }
218
219
220 #ifdef BUF_SAVE_MODE
221         g_count++;
222
223         snprintf(g_temp_file_name, sizeof(g_temp_file_name), "/tmp/stt_temp_%d_%d", getpid(), g_count);
224         SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Temp file name=[%s]", g_temp_file_name);
225
226         /* open test file */
227         g_pFile = fopen(g_temp_file_name, "wb+");
228         if (!g_pFile) {
229                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] File not found!");
230                 return -1;
231         }       
232 #endif  
233
234         return 0;
235 }
236
237 int sttd_recorder_stop()
238 {
239         if (STTD_RECORDER_STATE_READY == g_recorder_state)
240                 return 0;
241
242         g_recorder_state = STTD_RECORDER_STATE_READY;
243
244         int ret = STTD_ERROR_OPERATION_FAILED; 
245         ret = audio_in_unprepare(g_audio_in_h);
246         if (AUDIO_IO_ERROR_NONE != ret) {
247                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to unprepare audio_in : %d", ret);
248         }
249
250         fclose(g_pFile_vol);
251
252 #ifdef BUF_SAVE_MODE
253         fclose(g_pFile);
254 #endif  
255
256         SLOG(LOG_ERROR, TAG_STTD, "[Recorder] Recorder stop success");
257         return 0;
258 }