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