1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  *
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include <signal.h>
11 
12 #include "uvoice_os.h"
13 #include "uvoice_types.h"
14 #include "uvoice_player.h"
15 
16 #include "uvoice_common.h"
17 #include "uvoice_play.h"
18 
19 #include "opensource/speex/include/speex/speex_callbacks.h"
20 
21 
22 typedef struct {
23 	void *speex;
24 	SpeexBits bits;
25 	int frame_size;
26 	int bitwidth;
27 	int rate;
28 	int channels;
29 	int bitrate;
30 } spx_decoder_t;
31 
32 static int spx_rate;
33 static int spx_channels;
34 
spx_rate_valid(int rate)35 static bool spx_rate_valid(int rate)
36 {
37 	switch (rate) {
38 	case 8000:
39 	case 12000:
40 	case 16000:
41 	case 24000:
42 	case 48000:
43 		return true;
44 	}
45 	return false;
46 }
47 
spx_channels_valid(int channels)48 static bool spx_channels_valid(int channels)
49 {
50 	if (channels == 1 || channels == 2)
51 		return true;
52 	return false;
53 }
54 
spx_decoder_reset(void * priv)55 static int spx_decoder_reset(void *priv)
56 {
57 	media_decoder_t *mdecoder = (media_decoder_t *)priv;
58 	if (!mdecoder) {
59 		M_LOGE("mdecoder null !\n");
60 		return -1;
61 	}
62 
63 	spx_decoder_t *spx = mdecoder->decoder;
64 	if (!spx) {
65 		M_LOGE("spx decoder null !\n");
66 		return -1;
67 	}
68 
69 	M_LOGD("speex decoder reset\n");
70 	return 0;
71 }
72 
spx_decoder_process(void * priv,uint8_t * buffer,int nbytes)73 static int spx_decoder_process(void *priv, uint8_t *buffer, int nbytes)
74 {
75 	media_decoder_t *mdecoder = (media_decoder_t *)priv;
76 	if (!mdecoder) {
77 		M_LOGE("mdecoder null !\n");
78 		return -1;
79 	}
80 
81 	spx_decoder_t *spx = mdecoder->decoder;
82 	if (!spx) {
83 		M_LOGE("speex null !\n");
84 		return -1;
85 	}
86 
87 	SpeexBits *bits = &spx->bits;
88 
89 	spx_int16_t *out_buffer = (spx_int16_t *)mdecoder->buffer_out;
90 	int offset = 0;
91 	int frame_size;
92 	int ret;
93 	int i;
94 
95 	while (1) {
96 		frame_size = *(int *)(buffer + offset);
97 		offset += 4;
98 		if (frame_size > nbytes - offset) {
99 			mdecoder->unproc_size = nbytes - offset + 4;
100 			break;
101 		}
102 		snd_memcpy(bits->chars, buffer + offset, frame_size);
103 
104 		bits->nbBits = frame_size << 3;
105 		speex_bits_rewind(&spx->bits);
106 
107 		ret = speex_decode_int(spx->speex, bits, out_buffer);
108 
109 		offset += frame_size;
110 
111 		if (!mdecoder->running) {
112 			if (mdecoder->message) {
113 				spx_int32_t temp = 0;
114 				speex_decoder_ctl(spx->speex, SPEEX_GET_BITRATE, &temp);
115 				spx->bitrate = temp;
116 				//M_LOGD("rate %d, channels %d, bitrate %d, frame_size %d, bits %d\n",
117 				//		spx->rate,
118 				//		spx->channels,
119 				//		spx->bitrate,
120 				//		spx->frame_size, 16);
121 				media_pcminfo_t pcm_info;
122 				memset(&pcm_info, 0, sizeof(pcm_info));
123 				pcm_info.rate = spx->rate;
124 				pcm_info.frames = spx->frame_size / spx->channels;
125 				if (mdecoder->stere_enable)
126 					pcm_info.channels = spx->channels;
127 				else
128 					pcm_info.channels = 1;
129 				pcm_info.bits = 16;
130 				mdecoder->message(mdecoder->priv,
131 					PLAYER_MSG_PCM_INFO, &pcm_info);
132 
133 				media_info_t media_info;
134 				memset(&media_info, 0, sizeof(media_info_t));
135 				media_info.bitrate = spx->bitrate;
136 				mdecoder->message(mdecoder->priv,
137 					PLAYER_MSG_MEDIA_INFO, &media_info);
138 			}
139 			mdecoder->running = 1;
140 		}
141 
142 		if (mdecoder->output(mdecoder->priv, mdecoder->buffer_out,
143 				spx->frame_size * sizeof(short))) {
144 			M_LOGE("output failed !\n");
145 			return -1;
146 		}
147 	}
148 
149 	speex_bits_reset(&spx->bits);
150 
151 __exit:
152 	return 0;
153 }
154 
spx_decoder_action(void * priv,player_action_t action,void * arg)155 static int spx_decoder_action(void *priv,
156 		player_action_t action, void *arg)
157 {
158 	media_decoder_t *mdecoder = (media_decoder_t *)priv;
159 	spx_decoder_t *spx;
160 	spx_int32_t temp;
161 	int ret;
162 
163 	if (!mdecoder) {
164 		M_LOGE("mdecoder null !\n");
165 		return -1;
166 	}
167 
168 	spx = mdecoder->decoder;
169 	if (!spx) {
170 		M_LOGE("spx decoder null !\n");
171 		return -1;
172 	}
173 
174 	if (action == PLAYER_CONFIGURE) {
175 		media_pcminfo_t *pcminfo = arg;
176 		if (!pcminfo) {
177 			M_LOGE("pcm info null !\n");
178 			return -1;
179 		}
180 
181 		if (!spx_rate_valid(pcminfo->rate)) {
182 			M_LOGE("sample rate invalid !\n");
183 			return -1;
184 		}
185 
186 		spx->rate = pcminfo->rate;
187 		spx_rate = spx->rate;
188 		temp = spx->rate;
189 		speex_decoder_ctl(spx->speex, SPEEX_SET_SAMPLING_RATE, &temp);
190 
191 		if (!spx_channels_valid(pcminfo->channels)) {
192 			M_LOGE("channels invalid !\n");
193 			return -1;
194 		}
195 		spx->channels = pcminfo->channels;
196 		spx_channels = spx->channels;
197 
198 		M_LOGD("rate %d channels %d\n", spx->rate, spx->channels);
199 	} else if (action == PLAYER_START ||
200 			action == PLAYER_RESUME || action == STREAM_MGR_START) {
201 		int error = -1;
202 		if (!spx_rate_valid(spx->rate)) {
203 			if (spx_rate_valid(spx_rate)) {
204 				spx->rate = spx_rate;
205 			} else {
206 				M_LOGE("no valid rate !\n");
207 				return -1;
208 			}
209 		}
210 
211 		if (!spx_channels_valid(spx->channels)) {
212 			if (spx_channels_valid(spx_channels)) {
213 				spx->channels = spx_channels;
214 			} else {
215 				M_LOGE("no valid channels !\n");
216 				return -1;
217 			}
218 		}
219 
220 		M_LOGD("rate %d channels %d\n", spx->rate, spx->channels);
221 	}
222 
223 	return 0;
224 }
225 
spx_decoder_create(media_decoder_t * mdecoder)226 int spx_decoder_create(media_decoder_t *mdecoder)
227 {
228 	spx_decoder_t *spx;
229 	spx_int32_t temp;
230 
231 	if (!mdecoder) {
232 		M_LOGE("mdecoder null !\n");
233 		return -1;
234 	}
235 
236 	spx = snd_zalloc(sizeof(spx_decoder_t), AFM_MAIN);
237 	if (!spx) {
238 		M_LOGE("alloc speex decoder failed !\n");
239 		return -1;
240 	}
241 
242 	spx->speex = speex_decoder_init(
243 		speex_lib_get_mode(SPEEX_MODEID_NB));
244 	if (!spx->speex) {
245 		M_LOGE("init speex failed !\n");
246 		snd_free(spx);
247 		return -1;
248 	}
249 
250 	speex_bits_init(&spx->bits);
251 
252 	temp = 1;
253 	speex_decoder_ctl(spx->speex, SPEEX_SET_HIGHPASS, &temp);
254 	temp = 1;
255 	speex_decoder_ctl(spx->speex, SPEEX_SET_ENH, &temp);
256 	speex_decoder_ctl(spx->speex, SPEEX_GET_FRAME_SIZE, &temp);
257 	spx->frame_size = temp;
258 	M_LOGD("frame size %d\n", spx->frame_size);
259 
260 	mdecoder->buffer_out_size = spx->frame_size * sizeof(short);
261 	mdecoder->buffer_out = snd_zalloc(mdecoder->buffer_out_size, AFM_EXTN);
262 	if (!mdecoder->buffer_out) {
263 		M_LOGE("alloc out buffer failed !\n");
264 		speex_decoder_destroy(spx->speex);
265 		speex_bits_destroy(&spx->bits);
266 		snd_free(spx);
267 		return -1;
268 	}
269 
270 	mdecoder->input_size = spx->bits.buf_size;
271 
272 	mdecoder->decoder = spx;
273 	mdecoder->decode = spx_decoder_process;
274 	mdecoder->action = spx_decoder_action;
275 	mdecoder->reset = spx_decoder_reset;
276 
277 	M_LOGD("speex decoder create\n");
278 	return 0;
279 }
280 
spx_decoder_release(media_decoder_t * mdecoder)281 int spx_decoder_release(media_decoder_t *mdecoder)
282 {
283 	spx_decoder_t *spx;
284 
285 	if (!mdecoder) {
286 		M_LOGE("mdecoder null !\n");
287 		return -1;
288 	}
289 
290 	spx = mdecoder->decoder;
291 	if (!spx) {
292 		M_LOGE("speex decoder null !\n");
293 		return -1;
294 	}
295 
296 	speex_decoder_destroy(spx->speex);
297 	speex_bits_destroy(&spx->bits);
298 	snd_free(spx);
299 	mdecoder->decoder = NULL;
300 
301 	M_LOGD("speex decoder release\n");
302 	return 0;
303 }
304