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