346 lines
8.7 KiB
C
Executable File
346 lines
8.7 KiB
C
Executable File
/*
|
|
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "kernel/os/os.h"
|
|
#include "common/apps/player_app.h"
|
|
#include "fs/vfs.h"
|
|
#include "audiofifo.h"
|
|
#include "audio/pcm/audio_pcm.h"
|
|
#include "audio/manager/audio_manager.h"
|
|
#include "audio/drc/drc.h"
|
|
#include "audio/eq/eq.h"
|
|
|
|
|
|
#define PLAYER_THREAD_STACK_SIZE (1024 * 4)
|
|
|
|
#define PLAYER_DRC_EN 0
|
|
#define PLAYER_EQ_EN 0
|
|
|
|
static OS_Thread_t play_thread;
|
|
static player_base *player;
|
|
static int isCompleted = 0;
|
|
|
|
#if PLAYER_DRC_EN
|
|
static const drc_user_params_t drc_user_params_example = {
|
|
.rms_average_time = 1, //RMS averaging time in ms, typical value is 1ms
|
|
.attack_time = 1, //attack time in ms, typical value is 1ms
|
|
.release_time = 100, //release time in ms, typical value is 100ms
|
|
.target_level = -12, //target level in dB <=0
|
|
};
|
|
#endif
|
|
|
|
#if PLAYER_EQ_EN
|
|
static eq_core_prms_t core_prms[10] = {
|
|
{0, 100, 2, HIGHPASS},
|
|
{-1, 200, 1, BANDPASS_PEAK},
|
|
{-3, 400, 1, BANDPASS_PEAK},
|
|
{3, 800, 2, BANDPASS_PEAK},
|
|
{0, 1000, 1, BANDPASS_PEAK},
|
|
{5, 2000, 1, BANDPASS_PEAK},
|
|
{-3, 4000, 2, BANDPASS_PEAK},
|
|
{5, 8000, 1, BANDPASS_PEAK},
|
|
{0, 12000, 1, BANDPASS_PEAK},
|
|
{0, 16000, 1, BANDPASS_PEAK},
|
|
};
|
|
static const eq_user_params_t eq_user_params_example = {
|
|
.biq_num = 10,
|
|
.core_params = (eq_core_prms_t *)&core_prms,
|
|
};
|
|
#endif
|
|
|
|
static void player_demo_callback(player_events event, void *data, void *arg)
|
|
{
|
|
switch (event) {
|
|
case PLAYER_EVENTS_MEDIA_PREPARED:
|
|
printf("media is prepared. play media now.\n");
|
|
printf("you can use player to seek, get duration(by size), get current position(by tell) from now on.\n");
|
|
break;
|
|
case PLAYER_EVENTS_MEDIA_STOPPED:
|
|
printf("media is stopped by user.\n");
|
|
isCompleted = 1;
|
|
break;
|
|
case PLAYER_EVENTS_MEDIA_ERROR:
|
|
printf("error occur\n");
|
|
isCompleted = 1;
|
|
break;
|
|
case PLAYER_EVENTS_MEDIA_PLAYBACK_COMPLETE:
|
|
printf("media play is completed\n");
|
|
isCompleted = 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int play_file_music(void)
|
|
{
|
|
int ret;
|
|
int duration;
|
|
int position;
|
|
|
|
/*
|
|
* play media in file system.
|
|
* 1. in this example, you should create a folder named music in your file system
|
|
* 2. add 1.mp3 to this folder
|
|
*/
|
|
isCompleted = 0;
|
|
player->set_callback(player, player_demo_callback, NULL);
|
|
ret = player->play(player, "file://data/music/1.mp3");
|
|
if (ret != 0) {
|
|
printf("music play fail.\n");
|
|
return -1;
|
|
}
|
|
|
|
OS_Sleep(15);
|
|
printf("music pause now, last for 10s\n");
|
|
player->pause(player);
|
|
OS_Sleep(10);
|
|
|
|
printf("music resume now.\n");
|
|
player->resume(player);
|
|
|
|
OS_Sleep(20);
|
|
duration = player->size(player);
|
|
position = player->tell(player);
|
|
printf("this song is %dms in length, and it has play %dms\n", duration, position);
|
|
|
|
printf("we will seek to the half of this song now.\n");
|
|
player->seek(player, duration / 2);
|
|
|
|
position = player->tell(player);
|
|
printf("now this song has play %dms\n", position);
|
|
|
|
/* wait for playback complete */
|
|
while (!isCompleted) {
|
|
OS_MSleep(100);
|
|
}
|
|
|
|
/* stop it */
|
|
player->stop(player);
|
|
return 0;
|
|
}
|
|
|
|
static int play_flash_music(void)
|
|
{
|
|
int ret;
|
|
|
|
/*
|
|
* play media in flash.
|
|
* 1. in this example, we play 1.amr(in image/xr872)
|
|
* 2. we should add 1.amr to our image.cfg, so we can write it to flash
|
|
* 3. construct the url according to the offset and size of 1.amr.
|
|
* in this example, the offset of 1.amr is (1024 * 1024 + 64) = 1048640,
|
|
* and the size of 1.amr is 363750 bytes. so url is "flash://0?addr=1048640&length=363750"
|
|
* be attention, we will add 64 bytes before the bin in image.cfg, so the offset of 1.amr is (1024 * 1024 + 64)
|
|
*/
|
|
isCompleted = 0;
|
|
player->set_callback(player, player_demo_callback, NULL);
|
|
ret = player->play(player, "flash://0?addr=1048640&length=363750");
|
|
if (ret != 0) {
|
|
printf("music play fail.\n");
|
|
return -1;
|
|
}
|
|
|
|
/* wait for playback complete */
|
|
while (!isCompleted) {
|
|
OS_MSleep(100);
|
|
}
|
|
|
|
/* stop it */
|
|
player->stop(player);
|
|
return 0;
|
|
}
|
|
|
|
static int play_fifo_music(void)
|
|
{
|
|
vfs_file_t *vfs;
|
|
int ret = 0;
|
|
void *file_buffer;
|
|
unsigned int act_read;
|
|
struct AudioFifoS *audiofifo;
|
|
|
|
/*
|
|
* play media by putting media data to player
|
|
* 1. only support mp3/amr/wav
|
|
*/
|
|
audiofifo = audio_fifo_create();
|
|
if (audiofifo == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
file_buffer = (void *)malloc(1024);
|
|
if (file_buffer == NULL) {
|
|
ret = -1;
|
|
goto err1;
|
|
}
|
|
|
|
vfs = vfs_open("data/music/1.mp3", VFS_RDONLY);
|
|
if (vfs == NULL) {
|
|
ret = -1;
|
|
goto err2;
|
|
}
|
|
|
|
AudioFifoSetPlayer(audiofifo, player);
|
|
AudioFifoStart(audiofifo);
|
|
while (1) {
|
|
act_read = vfs_read(vfs, file_buffer, 1024);
|
|
AudioFifoPutData(audiofifo, file_buffer, act_read);
|
|
if (act_read != 1024)
|
|
break;
|
|
}
|
|
AudioFifoStop(audiofifo, false);
|
|
|
|
vfs_close(vfs);
|
|
err2:
|
|
free(file_buffer);
|
|
err1:
|
|
audio_fifo_destroy(audiofifo);
|
|
return ret;
|
|
}
|
|
|
|
static int play_pcm_music(void)
|
|
{
|
|
vfs_file_t *vfs;
|
|
int ret;
|
|
unsigned int act_read;
|
|
unsigned int pcm_buf_size;
|
|
void *pcm_buf;
|
|
struct pcm_config config;
|
|
|
|
vfs = vfs_open("data/music/16000_1.pcm", VFS_RDONLY);
|
|
if (vfs == NULL) {
|
|
printf("open pcm file fail\n");
|
|
return -1;
|
|
}
|
|
|
|
config.channels = 1;
|
|
config.format = PCM_FORMAT_S16_LE;
|
|
config.period_count = 2;
|
|
config.period_size = 1024;
|
|
config.rate = 16000;
|
|
ret = snd_pcm_open(AUDIO_SND_CARD_DEFAULT, PCM_OUT, &config);
|
|
if (ret != 0) {
|
|
goto err1;
|
|
}
|
|
|
|
pcm_buf_size = config.channels * config.period_count * config.period_size;
|
|
pcm_buf = malloc(pcm_buf_size);
|
|
if (pcm_buf == NULL) {
|
|
goto err2;
|
|
}
|
|
|
|
while (1) {
|
|
act_read = vfs_read(vfs, pcm_buf, pcm_buf_size);
|
|
if (act_read < 0) {
|
|
printf("read fail.\n");
|
|
break;
|
|
}
|
|
|
|
snd_pcm_write(AUDIO_SND_CARD_DEFAULT, pcm_buf, act_read);
|
|
|
|
if (act_read != pcm_buf_size) {
|
|
printf("reach file end\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
free(pcm_buf);
|
|
snd_pcm_flush(AUDIO_SND_CARD_DEFAULT);
|
|
snd_pcm_close(AUDIO_SND_CARD_DEFAULT, PCM_OUT);
|
|
vfs_close(vfs);
|
|
|
|
return 0;
|
|
|
|
err2:
|
|
snd_pcm_close(AUDIO_SND_CARD_DEFAULT, PCM_OUT);
|
|
err1:
|
|
vfs_close(vfs);
|
|
return -1;
|
|
}
|
|
|
|
static void play_task(void *arg)
|
|
{
|
|
player = player_create();
|
|
if (player == NULL) {
|
|
printf("player create fail.\n");
|
|
goto exit;
|
|
}
|
|
|
|
printf("player create success.\n");
|
|
printf("you can use it to play, pause, resume, set volume and so on.\n");
|
|
|
|
printf("player set volume to 16. valid volume value is from 0~31\n");
|
|
player->setvol(player, 16);
|
|
|
|
#if PLAYER_DRC_EN
|
|
audio_filter_register(AUDIO_SND_CARD_DEFAULT, AUDIO_FILTER_DRC, (void *)&drc_user_params_example);
|
|
#endif
|
|
|
|
#if PLAYER_EQ_EN
|
|
audio_filter_register(AUDIO_SND_CARD_DEFAULT, AUDIO_FILTER_EQ, (void *)&eq_user_params_example);
|
|
#endif
|
|
|
|
while (1) {
|
|
printf("===try to play media in file system===\n");
|
|
play_file_music();
|
|
|
|
printf("===try to play media in flash===\n");
|
|
play_flash_music();
|
|
|
|
printf("===try to play media by fifo===\n");
|
|
play_fifo_music();
|
|
|
|
printf("===try to play pcm by audio driver===\n");
|
|
play_pcm_music();
|
|
}
|
|
|
|
player_destroy(player);
|
|
|
|
exit:
|
|
OS_ThreadDelete(&play_thread);
|
|
}
|
|
|
|
int audio_play_start(void)
|
|
{
|
|
if (OS_ThreadCreate(&play_thread,
|
|
"play_task",
|
|
play_task,
|
|
NULL,
|
|
OS_THREAD_PRIO_APP,
|
|
PLAYER_THREAD_STACK_SIZE) != OS_OK) {
|
|
printf("thread create fail.exit\n");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|