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_recorder.h"
15
16 #include "uvoice_common.h"
17 #include "uvoice_record.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 } spx_encoder_t;
27
spx_encode_process(void * priv,uint8_t * buffer,int nbytes)28 static int spx_encode_process(void *priv, uint8_t *buffer, int nbytes)
29 {
30 media_encoder_t *mencoder = (media_encoder_t *)priv;
31 if (!mencoder) {
32 M_LOGE("mencoder null !\n");
33 return -1;
34 }
35
36 spx_encoder_t *spx = mencoder->encoder;
37 if (!spx) {
38 M_LOGE("speex null !\n");
39 return -1;
40 }
41
42 spx_int16_t *ptr;
43 int samples = nbytes / sizeof(short);
44 int encode_sum = 0;
45 int frame_size = 0;
46 int ret;
47 int i;
48
49 int time_ms = os_current_time();
50
51 for (i = 0; i < samples; i += spx->frame_size) {
52 speex_bits_reset(&spx->bits);
53 ptr = (spx_int16_t *)buffer + i;
54 speex_encode_int(spx->speex, ptr, &spx->bits);
55 frame_size = speex_bits_write(&spx->bits, buffer + encode_sum + sizeof(int),
56 spx->frame_size * sizeof(spx_int16_t));
57 if (frame_size + sizeof(int) >= spx->frame_size * sizeof(spx_int16_t)) {
58 M_LOGE("encoded data overflow !\n");
59 return -1;
60 }
61 snd_memcpy(buffer + encode_sum, &frame_size, sizeof(int));
62 encode_sum += frame_size + sizeof(int);
63 }
64
65 //time_ms = os_current_time() - time_ms;
66 //M_LOGD("time %dms ratio %d/%d\n", time_ms, frame_size, nbytes);
67
68 return encode_sum;
69 }
70
spx_encode_action(void * priv,recorder_action_t action,void * arg)71 static int spx_encode_action(void *priv, recorder_action_t action, void *arg)
72 {
73 media_encoder_t *mencoder = (media_encoder_t *)priv;
74 spx_encoder_t *spx;
75 int ret;
76
77 if (!mencoder) {
78 M_LOGE("mencoder null !\n");
79 return -1;
80 }
81
82 spx = mencoder->encoder;
83 if (!spx) {
84 M_LOGE("spx encoder null !\n");
85 return -1;
86 }
87
88 if (action == RECORDER_START) {
89 if ((mencoder->frames * mencoder->channels) % spx->frame_size != 0) {
90 M_LOGE("frame size is not integral multiple of %d !\n",
91 spx->frame_size);
92 return -1;
93 }
94 }
95
96 return 0;
97 }
98
spx_encoder_create(media_encoder_t * mencoder)99 int spx_encoder_create(media_encoder_t *mencoder)
100 {
101 spx_encoder_t *spx;
102 spx_int32_t temp;
103
104 if (!mencoder) {
105 M_LOGE("mencoder null !\n");
106 return -1;
107 }
108
109 spx = snd_zalloc(sizeof(spx_encoder_t), AFM_MAIN);
110 if (!spx) {
111 M_LOGE("alloc speex encoder failed !\n");
112 return -1;
113 }
114
115 spx->speex = speex_encoder_init(
116 speex_lib_get_mode(SPEEX_MODEID_NB)); //nb_encoder_init()
117 if (!spx->speex) {
118 M_LOGE("init speex failed !\n");
119 snd_free(spx);
120 return -1;
121 }
122
123 temp = 0;
124 speex_encoder_ctl(spx->speex, SPEEX_SET_VBR, &temp); //nb_encoder_ctl()
125 temp = 2;
126 speex_encoder_ctl(spx->speex, SPEEX_SET_QUALITY, &temp);
127 temp = 2;
128 speex_encoder_ctl(spx->speex, SPEEX_SET_COMPLEXITY, &temp);
129
130 speex_encoder_ctl(spx->speex, SPEEX_GET_FRAME_SIZE, &spx->frame_size);
131 M_LOGD("speex frame size %d\n", spx->frame_size); /* frame size in sizeof(short) */
132
133 speex_bits_init(&spx->bits);
134
135 mencoder->encoder = spx;
136 mencoder->encode = spx_encode_process;
137 mencoder->action = spx_encode_action;
138
139 M_LOGI("speex encoder create\n");
140 return 0;
141 }
142
spx_encoder_release(media_encoder_t * mencoder)143 int spx_encoder_release(media_encoder_t *mencoder)
144 {
145 spx_encoder_t *spx;
146
147 if (!mencoder) {
148 M_LOGE("mencoder null !\n");
149 return -1;
150 }
151
152 spx = mencoder->encoder;
153 if (!spx) {
154 M_LOGE("speex encoder null !\n");
155 return -1;
156 }
157
158 speex_bits_destroy(&spx->bits);
159 speex_encoder_destroy(spx->speex);
160 snd_free(spx);
161 mencoder->encoder = NULL;
162
163 M_LOGI("speex encoder release\n");
164 return 0;
165 }