1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 *
4 */
5
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <math.h>
11
12 #include "uvoice_types.h"
13 #include "uvoice_event.h"
14 #include "uvoice_player.h"
15 #include "uvoice_recorder.h"
16
17 #include "uvoice_os.h"
18
19 static os_task_t play_task;
20
21 static uvoice_player_t *uvocplayer;
22
23 static char text_source[256];
24
25 static int source_sample_rate;
26 static int source_channels;
27
get_format_from_name(char * name,media_format_t * format)28 static int get_format_from_name(char *name, media_format_t *format)
29 {
30 if (!name || !format) {
31 M_LOGE("arg null !\n");
32 return -1;
33 }
34
35 if (strstr(name, ".mp3") || strstr(name, ".MP3"))
36 *format = MEDIA_FMT_MP3;
37 else if (strstr(name, ".wav") || strstr(name, ".WAV"))
38 *format = MEDIA_FMT_WAV;
39 else if (strstr(name, ".aac") || strstr(name, ".AAC"))
40 *format = MEDIA_FMT_AAC;
41 else if (strstr(name, ".m4a") || strstr(name, ".M4A"))
42 *format = MEDIA_FMT_M4A;
43 else if (strstr(name, ".pcm") || strstr(name, ".PCM"))
44 *format = MEDIA_FMT_PCM;
45 else if (strstr(name, ".spx") || strstr(name, ".SPX"))
46 *format = MEDIA_FMT_SPX;
47 else if (strstr(name, ".ogg") || strstr(name, ".OGG"))
48 *format = MEDIA_FMT_OGG;
49 else if (strstr(name, ".amrwb") || strstr(name, ".AMRWB"))
50 *format = MEDIA_FMT_AMRWB;
51 else if (strstr(name, ".amr") || strstr(name, ".AMR"))
52 *format = MEDIA_FMT_AMR;
53 else if (strstr(name, ".opus") || strstr(name, ".OPUS"))
54 *format = MEDIA_FMT_OPS;
55 else if (strstr(name, ".flac") || strstr(name, ".FLAC"))
56 *format = MEDIA_FMT_FLAC;
57
58 return 0;
59 }
60
uvoice_st_event_cb(uvoice_event_t * event,void * data)61 static void uvoice_st_event_cb(uvoice_event_t *event, void *data)
62 {
63 if (event->type != UVOICE_EV_ST)
64 return;
65
66 if (event->code == UVOICE_CODE_VAD_START)
67 printf("vad ---->begin\n");
68 else if (event->code == UVOICE_CODE_VAD_END)
69 printf("vad ---->end\n");
70 }
71
72 /* usage: play sine 16000 16 1 1000 */
play_sine_wave(int rate,int bits,int channels,int freq_hz)73 static int play_sine_wave(int rate, int bits, int channels, int freq_hz)
74 {
75 #define PI 3.14159265
76 #define CYCLES_PER_PERIOD 8
77 if (freq_hz == 0) {
78 return -1;
79 }
80 unsigned int samples_per_cycle = rate / freq_hz;
81 unsigned int samples_per_period = samples_per_cycle * CYCLES_PER_PERIOD;
82 unsigned int sample_size = (bits >> 3) * channels;
83
84 if (bits != 8 && bits != 16 && bits != 24) {
85 M_LOGE("bits %d invalid !\n", bits);
86 return -1;
87 }
88
89 if (channels != 1 && channels != 2) {
90 M_LOGE("channels %d invalid !\n", channels);
91 return -1;
92 }
93
94 char *samples_data = snd_zalloc(sample_size * samples_per_cycle, AFM_MAIN);
95 if (!samples_data) {
96 M_LOGE("alloc samples_data failed !\n");
97 return -1;
98 }
99
100 char *period_buffer = snd_zalloc(sample_size * samples_per_period, AFM_MAIN);
101 if (!period_buffer) {
102 M_LOGE("alloc period_buffer failed !\n");
103 snd_free(samples_data);
104 return -1;
105 }
106
107 unsigned int msec_per_period = (samples_per_period * 1000) / rate;
108 unsigned int play_msec = 0;
109 unsigned int sample_val;
110 unsigned int sample_idx;
111 unsigned int cycle_idx;
112
113 double sin_float;
114 double triangle_float;
115 double triangle_step = (double)pow(2, bits) / samples_per_cycle;
116
117 M_LOGI("sample_size %d samper_per_cycly %d msec_per_period %d\n",
118 sample_size, samples_per_cycle, msec_per_period);
119
120 triangle_float = -(pow(2, bits) / 2 - 1);
121
122 for (sample_idx = 0; sample_idx < samples_per_cycle; sample_idx++) {
123 sin_float = sin(sample_idx * PI / 180.0);
124 if (sin_float >= 0)
125 triangle_float += triangle_step;
126 else
127 triangle_float -= triangle_step;
128
129 sin_float *= (pow(2, bits) / 2 - 1);
130
131 if (bits == 16) {
132 sample_val = 0;
133 sample_val += (short)triangle_float;
134 sample_val = sample_val << 16;
135 sample_val += (short)sin_float;
136 samples_data[sample_idx] = sample_val;
137 } else if (bits == 24) {
138 samples_data[sample_idx * 2] = ((int)triangle_float) << 8;
139 samples_data[sample_idx * 2 + 1] = ((int)sin_float) << 8;
140 } else {
141 samples_data[sample_idx * 2] = (int)triangle_float;
142 samples_data[sample_idx * 2 + 1] = (int)sin_float;
143 }
144 }
145
146 for (cycle_idx = 0; cycle_idx < CYCLES_PER_PERIOD; cycle_idx++) {
147 memcpy(period_buffer + cycle_idx * (sample_size * samples_per_cycle),
148 samples_data,
149 samples_per_cycle * sample_size);
150 }
151
152 M_LOGI("start\n");
153
154 player_state_t player_state = -1;
155 bool player_paused = false;
156 uvocplayer->get_state(&player_state);
157 if (player_state == PLAYER_STAT_RUNNING ||
158 player_state == PLAYER_STAT_COMPLETE) {
159 uvocplayer->set_fade(40, 60);
160 uvocplayer->pause();
161 player_paused = true;
162 }
163
164 uvocplayer->set_stream(MEDIA_FMT_PCM, 0, 0);
165 uvocplayer->set_pcminfo(rate, channels, bits, samples_per_period);
166
167 while (play_msec <= 5000) {
168 uvocplayer->put_stream(period_buffer, sample_size * samples_per_period);
169 play_msec += msec_per_period;
170 }
171
172 uvocplayer->clr_stream(1);
173
174 if (player_paused) {
175 uvocplayer->set_fade(40, 60);
176 uvocplayer->resume();
177 player_paused = false;
178 }
179
180 snd_free(period_buffer);
181 snd_free(samples_data);
182
183 M_LOGI("exit\n");
184 return 0;
185 }
186
play_music(void * arg)187 static void play_music(void *arg)
188 {
189 media_format_t format = MEDIA_FMT_UNKNOWN;
190 get_format_from_name(text_source, &format);
191
192 if (uvocplayer->set_source(text_source)) {
193 M_LOGE("set source failed !\n");
194 os_task_exit(NULL);
195 return;
196 }
197
198 if (format == MEDIA_FMT_OPS || format == MEDIA_FMT_SPX)
199 uvocplayer->set_pcminfo(source_sample_rate, source_channels, 16, 1280);
200
201 if (uvocplayer->start()) {
202 M_LOGE("start failed !\n");
203 uvocplayer->clr_source();
204 }
205
206 os_task_exit(NULL);
207 }
208
play_loopback(void * arg)209 static void play_loopback(void *arg)
210 {
211 #ifdef UVOICE_RECORDER_ENABLE
212 #define LOOPBACK_TEST_DURATION_SEC 20
213 unsigned char *read_buffer;
214 int read_samples = 640;
215 int channels = 2;
216 int rate = 32000;
217 int bits = 16;
218 int buffer_size;
219 int i = 0;
220
221 int count = (LOOPBACK_TEST_DURATION_SEC * 1000) / (read_samples / (rate / 1000));
222
223 buffer_size = read_samples * channels * (bits >> 3);
224 read_buffer = malloc(buffer_size);
225 if (!read_buffer) {
226 M_LOGE("alloc read buffer failed !\n");
227 os_task_exit(NULL);
228 return;
229 }
230
231 uvoice_recorder_t *mrecorder = uvoice_recorder_create();
232 if (!mrecorder) {
233 M_LOGE("create uvoice recorder failed !\n");
234 free(read_buffer);
235 os_task_exit(NULL);
236 return;
237 }
238
239 if (mrecorder->set_sink(MEDIA_FMT_PCM, rate, channels, bits, read_samples, 0, NULL)) {
240 M_LOGE("set record sink failed !\n");
241 uvoice_recorder_release(mrecorder);
242 free(read_buffer);
243 os_task_exit(NULL);
244 return;
245 }
246
247 uvocplayer->set_stream(MEDIA_FMT_PCM, 0, 0);
248 uvocplayer->set_pcminfo(rate, channels, bits, read_samples);
249 while (++i < count) {
250 mrecorder->get_stream(read_buffer, buffer_size);
251 uvocplayer->put_stream(read_buffer, buffer_size);
252 }
253 uvocplayer->clr_stream(0);
254
255 mrecorder->clr_sink();
256 uvoice_recorder_release(mrecorder);
257 free(read_buffer);
258 #endif
259 os_task_exit(NULL);
260 }
261
play_list_scan(void * arg)262 static void play_list_scan(void *arg)
263 {
264 #if (UVOICE_MLIST_ENABLE == 1)
265 mlist_source_scan();
266 #endif
267 os_task_exit(NULL);
268 }
269
play_list_del(void * arg)270 static void play_list_del(void *arg)
271 {
272 #if (UVOICE_MLIST_ENABLE == 1)
273 mlist_source_del((int)arg);
274 #endif
275 os_task_exit(NULL);
276 }
277
play_list_set(void * arg)278 static void play_list_set(void *arg)
279 {
280 #if (UVOICE_MLIST_ENABLE == 1)
281 mlist_index_set((int)arg);
282 #endif
283 os_task_exit(NULL);
284 }
285
play_equalizer_config(char * fc,char * width,char * gain)286 static void play_equalizer_config(char *fc, char *width, char *gain)
287 {
288 #ifdef UVOICE_EQ_ENABLE
289 extern char equalizer_opt_fc[16];
290 extern char equalizer_opt_width[16];
291 extern char equalizer_opt_gain[16];
292 snprintf(equalizer_opt_fc, 16, "%s", fc);
293 snprintf(equalizer_opt_width, 16, "%s", width);
294 snprintf(equalizer_opt_gain, 16, "%s", gain);
295 #endif
296 }
297
play_number(char * num)298 static void play_number(char *num)
299 {
300 #ifdef UVOICE_COMB_ENABLE
301 comb_init();
302 comb_alipay_number(atof(num));
303 #endif
304 }
305
play_music_stream(void * arg)306 static void play_music_stream(void *arg)
307 {
308 media_format_t format = MEDIA_FMT_UNKNOWN;
309 FILE *fp;
310 int buffer_size = 2048;
311 char *buffer;
312 int ret;
313
314 get_format_from_name(text_source, &format);
315
316 fp = fopen(text_source, "rb");
317 if (!fp) {
318 M_LOGE("open %s failed !\n", text_source);
319 os_task_exit(NULL);
320 return;
321 }
322
323 buffer = malloc(buffer_size);
324 if (!buffer) {
325 M_LOGE("alloc buffer failed !\n");
326 fclose(fp);
327 os_task_exit(NULL);
328 return;
329 }
330
331 ret = fread(buffer, 1, buffer_size, fp);
332 if (ret <= 0) {
333 M_LOGE("read failed %d!\n", ret);
334 fclose(fp);
335 free(buffer);
336 os_task_exit(NULL);
337 return;
338 } else if (ret != buffer_size) {
339 M_LOGI("read %d ret %d\n", buffer_size, ret);
340 }
341
342 if (uvocplayer->set_stream(format, 0, 8192)) {
343 fclose(fp);
344 free(buffer);
345 os_task_exit(NULL);
346 return;
347 }
348
349 if (format == MEDIA_FMT_OPS || format == MEDIA_FMT_SPX)
350 uvocplayer->set_pcminfo(source_sample_rate, source_channels, 16, 320);
351
352 while (ret > 0) {
353 if (uvocplayer->put_stream(buffer, ret))
354 break;
355 ret = fread(buffer, 1, buffer_size, fp);
356 if (ret < 0) {
357 M_LOGE("read failed %d!\n", ret);
358 uvocplayer->clr_stream(1);
359 fclose(fp);
360 free(buffer);
361 os_task_exit(NULL);
362 return;
363 } else if (ret == 0) {
364 M_LOGI("read end\n");
365 break;
366 } else if (ret != buffer_size) {
367 M_LOGI("read %d ret %d\n", buffer_size, ret);
368 }
369 }
370
371 uvocplayer->clr_stream(0);
372
373 fclose(fp);
374 free(buffer);
375 os_task_exit(NULL);
376 }
377
uvoice_play_test(int argc,char ** argv)378 void uvoice_play_test(int argc, char **argv)
379 {
380 if (!uvocplayer) {
381 uvocplayer = uvoice_player_create();
382 if (!uvocplayer) {
383 M_LOGE("create media player failed !\n");
384 return;
385 }
386 uvocplayer->eq_enable(0);
387
388 uvoice_event_register(UVOICE_EV_ST, uvoice_st_event_cb, NULL);
389 }
390
391 if (argc < 2 || strcmp(argv[0], "play"))
392 return;
393
394 if (!strcmp(argv[1], "stop")) {
395 uvocplayer->set_fade(40, 40);
396 uvocplayer->stop_async();
397 } else if (!strcmp(argv[1], "stopsync")) {
398 uvocplayer->set_fade(40, 40);
399 uvocplayer->stop();
400 } else if (!strcmp(argv[1], "source")) {
401 if (argc < 3)
402 return;
403 uvocplayer->set_source(argv[2]);
404 } else if (!strcmp(argv[1], "start")) {
405 uvocplayer->start();
406 } else if (!strcmp(argv[1], "clear")) {
407 uvocplayer->clr_source();
408 } else if (!strcmp(argv[1], "pause")) {
409 uvocplayer->set_fade(40, 40);
410 uvocplayer->pause_async();
411 } else if (!strcmp(argv[1], "pausesync")) {
412 uvocplayer->set_fade(40, 40);
413 uvocplayer->pause();
414 } else if (!strcmp(argv[1], "resume")) {
415 uvocplayer->set_fade(40, 40);
416 uvocplayer->resume();
417 } else if (!strcmp(argv[1], "complete")) {
418 uvocplayer->complete();
419 } else if (!strcmp(argv[1], "playback")) {
420 if (argc < 3)
421 return;
422 uvocplayer->playback(argv[2]);
423 } else if (!strcmp(argv[1], "dump")) {
424 uvocplayer->state_dump();
425 } else if (!strcmp(argv[1], "num")) {
426 if (argc < 3)
427 return;
428 play_number(argv[2]);
429 } else if (!strcmp(argv[1], "pcmdump")) {
430 uvocplayer->pcmdump_enable(atoi(argv[2]));
431 } else if (!strcmp(argv[1], "fade")) {
432 if (argc < 4)
433 return;
434 uvocplayer->set_fade(atoi(argv[2]), atoi(argv[3]));
435 } else if (!strcmp(argv[1], "sine")) {
436 if (argc < 6)
437 return;
438 play_sine_wave(atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]));
439 } else if (!strcmp(argv[1], "progress")) {
440 int position = 0;
441 int duration = 0;
442 uvocplayer->get_position(&position);
443 uvocplayer->get_duration(&duration);
444 printf("progress: %d/%d\n", position, duration);
445 } else if (!strcmp(argv[1], "seek")) {
446 if (argc < 3)
447 return;
448 uvocplayer->seek(atoi(argv[2]));
449 } else if (!strcmp(argv[1], "format")) {
450 if (argc < 3)
451 return;
452 uvocplayer->set_format(atoi(argv[2]));
453 } else if (!strcmp(argv[1], "standby")) {
454 if (argc < 3)
455 return;
456 uvocplayer->set_standby(atoi(argv[2]));
457 } else if (!strcmp(argv[1], "state")) {
458 player_state_t state = -1;
459 uvocplayer->get_state(&state);
460 printf("state %d\n", state);
461 } else if (!strcmp(argv[1], "loopback")) {
462 os_task_create(&play_task,
463 "loopback task", play_loopback,
464 NULL, 8192, 0);
465 } else if (!strcmp(argv[1], "eq")) {
466 if (argc >= 5) {
467 #ifdef UVOICE_EQ_ENABLE
468 play_equalizer_config(argv[2], argv[3], argv[4]);
469 #endif
470 return;
471 }
472 uvocplayer->eq_enable(atoi(argv[2]));
473 } else if (!strcmp(argv[1], "list")) {
474 #if (UVOICE_MLIST_ENABLE == 1)
475 if (argc == 2) {
476 mlist_source_show();
477 return;
478 }
479
480 if (argc == 4 && !strcmp(argv[2], "index") && !strcmp(argv[3], "get")) {
481 int index = 0;
482 if (mlist_index_get(&index)) {
483 M_LOGE("get index failed !\n");
484 return;
485 }
486 M_LOGI("current source index %d\n", index);
487 return;
488 }
489
490 if (argc == 5 && !strcmp(argv[2], "index") && !strcmp(argv[3], "set")) {
491 os_task_create(&play_task,
492 "list set task", play_list_set,
493 atoi(argv[4]), 4096, 0);
494 return;
495 }
496
497 if (argc == 3 && !strcmp(argv[2], "scan")) {
498 os_task_create(&play_task,
499 "player scan task", play_list_scan,
500 NULL, 4096, 0);
501 return;
502 }
503
504 if (argc == 3) {
505 int index = atoi(argv[2]);
506 char file_path[128];
507 memset(file_path, 0, sizeof(file_path));
508 if (mlist_source_get(index, file_path, sizeof(file_path))) {
509 M_LOGE("search list failed !\n");
510 return;
511 }
512 uvocplayer->set_source(file_path);
513 uvocplayer->start();
514 return;
515 }
516
517 if (argc == 4 && !strcmp(argv[2], "del")) {
518 os_task_create(&play_task,
519 "player del task", play_list_del,
520 atoi(argv[3]), 4096, 0);
521 return;
522 }
523 #endif
524 } else if (!strcmp(argv[1], "cacheinfo")) {
525 int cache_len = 0;
526 uvocplayer->get_cacheinfo(&cache_len);
527 printf("avail cache len %d\n", cache_len);
528 } else if (!strcmp(argv[1], "download")) {
529 if (argc >= 3) {
530 if (!strcmp(argv[2], "abort"))
531 uvocplayer->download_abort();
532 else
533 uvocplayer->download(argv[2]);
534 } else {
535 uvocplayer->download(NULL);
536 }
537 } else if (!strcmp(argv[1], "stream")) {
538 if (argc < 3)
539 return;
540 if (!strcmp(argv[2], "stop")) {
541 uvocplayer->clr_stream(1);
542 return;
543 }
544 memset(text_source, 0, sizeof(text_source));
545 snprintf(text_source, sizeof(text_source), "%s", argv[2]);
546 media_format_t format = MEDIA_FMT_UNKNOWN;
547 get_format_from_name(text_source, &format);
548 if (format == MEDIA_FMT_OPS || format == MEDIA_FMT_SPX) {
549 if (argc < 5) {
550 M_LOGE("args too less for this format\n");
551 return;
552 }
553 source_sample_rate = atoi(argv[3]);
554 source_channels = atoi(argv[4]);
555 }
556 os_task_create(&play_task,
557 "stream play task", play_music_stream,
558 NULL, 4096, 0);
559 } else if (!strcmp(argv[1], "volume")) {
560 if (argc >= 3) {
561 uvocplayer->set_volume(atoi(argv[2]));
562 } else {
563 int volume = 0;
564 uvocplayer->get_volume(&volume);
565 printf("volume %d\n", volume);
566 }
567 } else {
568 memset(text_source, 0, sizeof(text_source));
569 snprintf(text_source, sizeof(text_source), "%s", argv[1]);
570 media_format_t format = MEDIA_FMT_UNKNOWN;
571 get_format_from_name(text_source, &format);
572 if (format == MEDIA_FMT_OPS || format == MEDIA_FMT_SPX) {
573 if (argc < 4) {
574 M_LOGE("args too less for this format\n");
575 return;
576 }
577 source_sample_rate = atoi(argv[2]);
578 source_channels = atoi(argv[3]);
579 }
580 os_task_create(&play_task,
581 "play music task", play_music,
582 NULL, 8192, 0);
583 }
584 }
585
586