blob: d95ca9e41e8e51f64a00ef9cfd81c8f9e6b62ecc [file] [log] [blame]
#include "ql/ql_audio.h"
#include "mbtk_log.h"
#include "mbtk_audio2.h"
typedef enum {
AUDIO_PLAY_STATE_STOP,
AUDIO_PLAY_STATE_RUNNING,
AUDIO_PLAY_STATE_PAUSE
} audio_play_state_enum;
#define AUDIO_HANDLE 1
#define WAV_PLAY_BUFF 1024
#ifdef MBTK_AF_SUPPORT
static mbtk_audio_handle player_hdl = NULL;
static int player_hdl_1 = AUDIO_HANDLE;
static _cb_onRecorder record_cb_fun = NULL;
static int Samprate = 8000;
#endif
static int sample_rate = 8000;
static int play_handle = AUDIO_HANDLE;
static _cb_onPlayer play_cb_func = NULL;
static _cb_onRecorder recorder_cb_fun = NULL;
static int is_running = 0;
static audio_play_state_enum play_state = AUDIO_PLAY_STATE_STOP;
static int play_exit = 1;
static void recorder_cb_func(void *data, uint32 data_len)
{
if(recorder_cb_fun) {
recorder_cb_fun(AUD_RECORDER_START, (unsigned char*)data, data_len);
}
}
static int play_stream(unsigned char* pData, unsigned int length)
{
int rc, len, frames = 0;
int result = 0;
play_state = AUDIO_PLAY_STATE_RUNNING;
play_exit = 0;
int data_send = 0;
if (mbtk_audio_pcm_play_start()) {
printf("%s: error opening output device.", __FUNCTION__);
return -1;
}
if(pData && length > 0) {
while (play_state != AUDIO_PLAY_STATE_STOP) {
if(play_state == AUDIO_PLAY_STATE_RUNNING) {
if (data_send >= length) {
LOGE("%s: Read pcm stream end.", __FUNCTION__);
break;
}
if(length - data_send > WAV_PLAY_BUFF) {
len = WAV_PLAY_BUFF;
} else {
len = length - data_send;
}
if((rc = mbtk_audio_pcm_play_data_send(pData + data_send, len)) != len) {
LOGE("Send data %d/%d", rc, len);
result = -1;
goto thread_end;
}
data_send += len;
LOGD("%s: No.%d frame playback", __FUNCTION__, ++frames);
} else {
usleep(200000);
}
}
} else {
result = -1;
}
play_state = AUDIO_PLAY_STATE_STOP;
thread_end:
mbtk_audio_pcm_play_stop();
play_exit = 1;
LOGD("%s: finished pcm playback.", __FUNCTION__);
return result;
}
static int play_by_fd(int fd, int offset)
{
int rc, len, frames = 0;
int result = 0;
char buf[WAV_PLAY_BUFF];
play_state = AUDIO_PLAY_STATE_RUNNING;
if(play_cb_func)
play_cb_func(play_handle , AUDIO_PLAY_STATE_RUNNING);
play_exit = 0;
if(fd > 0) {
if(offset > 0) {
lseek(fd, offset, SEEK_SET);
}
if (mbtk_audio_pcm_play_start()) {
printf("%s: error opening output device.", __FUNCTION__);
return -1;
}
while (play_state != AUDIO_PLAY_STATE_STOP) {
if(play_state == AUDIO_PLAY_STATE_RUNNING) {
memset(buf, 0x00, sizeof(buf));
len = read(fd, buf, WAV_PLAY_BUFF);
if (len == -1) {
LOGE("%s: error reading from file", __FUNCTION__);
result = -1;
goto thread_end;
}
if (len == 0) {
/* reached EOF */
LOGE("%s: Read wav file end.", __FUNCTION__);
break;
}
if((rc = mbtk_audio_pcm_play_data_send(buf, len)) < len) {
LOGE("Send data %d/%d", rc, len);
result = -1;
goto thread_end;
}
LOGD("%s: No.%d frame playback", __FUNCTION__, ++frames);
} else {
usleep(200000);
}
}
} else {
result = -1;
}
play_state = AUDIO_PLAY_STATE_STOP;
if(play_cb_func)
play_cb_func(play_handle , AUDIO_PLAY_STATE_STOP);
thread_end:
mbtk_audio_pcm_play_stop();
play_exit = 1;
LOGD("%s: finished pcm playback.", __FUNCTION__);
return result;
}
/*****************************************************************
* Function: Ql_AudPlayer_Open
*
* Description:
* Open audio play device, and specify the callback function.
* This function can be called twice to play different audio sources.
*
* Parameters:
* device : a string that specifies the PCM device.
* NULL, means the audio will be played on the default PCM device.
*
* If you want to mixedly play audio sources, you can call this
* API twice with specifying different PCM device.
* The string devices available:
* "hw:0,0" (the default play device)
* "hw:0,13" (this device can mix audio and TTS)
* "hw:0,14"
*
* cb_func : callback function for audio player.
* The results of all operations on audio player
* are informed in callback function.
*
* Return:
* pcm device handle on success
* -1 for failure
*****************************************************************/
int Ql_AudPlayer_Open(char* device, _cb_onPlayer cb_func)
{
#ifdef MBTK_AF_SUPPORT
player_hdl = mbtk_audio_open_new(MBTK_AUTIO_TYPE_OUT, 1, Samprate, cb_func);
if(player_hdl == NULL)
{
return -1;
}
else
{
return player_hdl_1 = AUDIO_HANDLE;
}
#else
if(is_running || mbtk_audio_pcm_init()) {
return -1;
} else {
play_cb_func = cb_func;
is_running = 1;
return play_handle;
}
#endif
}
/*========================================================================
FUNCTION: Ql_AudPlayer_Play
=========================================================================*/
/** @brief
This function writes pcm data to pcm device to play.
@param[in] hdl, the handle returned by Ql_AudPlayer_Open().
@param[in] pData, pointer to the start address of pcm data.
@param[in] length, the length of pcm data.
@return
on success, the return value is the number of bytes to play
on failure, the return value is -1;
@dependencies
Ql_AudPlayer_Open() must be first called successfully.
*/
/*=======================================================================*/
int Ql_AudPlayer_Play(int hdl, unsigned char* pData, unsigned int length)
{
#ifdef MBTK_AF_SUPPORT
if(hdl != player_hdl_1 || player_hdl == NULL){
LOGE("Handle error : %d", hdl);
return -1;
}
return mbtk_audio_play_stream_new((void *)player_hdl, pData, length,50);
#else
if(!is_running || hdl != play_handle) {
LOGE("Handle error : %d", hdl);
return -1;
}
return play_stream(pData, length);
#endif
}
/*========================================================================
FUNCTION: Ql_AudPlayer_PlayFrmFile
=========================================================================*/
/** @brief
This function plays the pcm data from the specified file.
@param[in] hdl, the handle returned by Ql_AudPlayer_Open().
@param[in] fd, a file descriptor that contains pcm data.
Note:
the file offset should be set to the start position of pcm
data region, which means you should move the file offset
skipping the file header (such as wave header, amr header).
@param[in] offset, file offset. Please set it to -1 if no need to use.
@return
0 on success
-1 on failure
@dependencies
Ql_AudPlayer_Open() must be first called successfully.
*/
/*=======================================================================*/
int Ql_AudPlayer_PlayFrmFile(int hdl, int fd, int offset)
{
#ifdef MBTK_AF_SUPPORT
if(hdl != player_hdl_1 || player_hdl == NULL){
LOGE("Handle error : %d", hdl);
return -1;
}
return mbtk_audio_play_file_new((void *)player_hdl, fd, offset);
#else
if(!is_running || hdl != play_handle) {
LOGE("Handle error : %d", hdl);
return -1;
}
return play_by_fd(fd, offset);
#endif
}
//
// Function: Ql_AudPlayer_Pause
//
// Description:
// Pause playing.
// @param hdl:
// Handle received from Ql_AudPlayer_Open().
int Ql_AudPlayer_Pause(int hdl)
{
if(!is_running || hdl != play_handle) {
LOGE("Handle error : %d", hdl);
return -1;
}
play_state = AUDIO_PLAY_STATE_PAUSE;
while(!play_exit) {
usleep(10000);
}
return 0;
}
//
// Function: Ql_AudPlayer_Resume
//
// Description:
// Resume playing.
// @param hdl:
// Handle received from Ql_AudPlayer_Open().
int Ql_AudPlayer_Resume(int hdl)
{
if(!is_running || hdl != play_handle) {
LOGE("Handle error : %d", hdl);
return -1;
}
play_state = AUDIO_PLAY_STATE_RUNNING;
while(!play_exit) {
usleep(10000);
}
return 0;
}
//
// Function: Ql_AudPlayer_Stop
//
// Description:
// Stop playing audio
// hdl:
// Handle received from Ql_AudPlayer_Open().
void Ql_AudPlayer_Stop(int hdl)
{
if(!is_running || hdl != play_handle) {
LOGE("Handle error : %d", hdl);
return;
}
play_state = AUDIO_PLAY_STATE_STOP;
while(!play_exit) {
usleep(10000);
}
}
//
// Function: Ql_AudPlayer_Close
//
// Description:
// Close player, and free the resource.
// @param hdl:
// Handle received from Ql_AudPlayer_Open().
void Ql_AudPlayer_Close(int hdl)
{
#ifdef MBTK_AF_SUPPORT
if(hdl != player_hdl_1 || player_hdl == NULL){
LOGE("Handle error : %d", hdl);
return -1;
}
mbtk_audio_close_new((void *)player_hdl);
player_hdl_1 = 0;
#else
if(!is_running || hdl != play_handle) {
LOGE("Handle error : %d", hdl);
return;
}
play_state = AUDIO_PLAY_STATE_STOP;
while(!play_exit) {
usleep(10000);
}
is_running = 0;
mbtk_audio_pcm_deinit();
#endif
}
int Ql_AudPlayer_set_LessDataThreshold(int hdl, unsigned short threshSize)
{
return 0;
}
int Ql_AudPlayer_get_freeSpace(int hdl)
{
return 0;
}
/*****************************************************************
* Function: Ql_AudRecorder_Open
*
* Description:
* Open audio record device, and specify the callback function.
*
* Parameters:
* device : not used. MUST be NULL.
*
* cb_func : callback function for audio player.
* The results of all operations on audio recorder
* are informed in callback function.
*
* Return:
* pcm device handle
* -1 for failure
*****************************************************************/
int Ql_AudRecorder_Open(char* device, _cb_onRecorder cb_fun)
{
if(is_running || mbtk_audio_pcm_init()) {
return -1;
} else {
is_running = 1;
recorder_cb_fun = cb_fun;
return play_handle;
}
}
//
// Function: Ql_AudRecorder_StartRecord
//
// Description:
// Start to record.
// The record data is output in _cb_onRecorder.
//
// Return:
// 0 on success
// -1 on failure
int Ql_AudRecorder_StartRecord(void)
{
if(!is_running) {
LOGE("No open device.");
return -1;
}
return mbtk_audio_pcm_recorder_start(recorder_cb_func);
}
//
// Function: Ql_AudRecorder_Pause
//
// Description:
// Pause recording
int Ql_AudRecorder_Pause(void)
{
if(!is_running) {
LOGE("No open device.");
return -1;
}
return mbtk_audio_pcm_recorder_pause();
}
//
// Function: Ql_AudRecorder_Resume
//
// Description:
// Resume recording
int Ql_AudRecorder_Resume(void)
{
if(!is_running) {
LOGE("No open device.");
return -1;
}
return mbtk_audio_pcm_recorder_resume();
}
//
// Function: Ql_AudRecorder_Stop
//
// Description:
// Stop recording
void Ql_AudRecorder_Stop(void)
{
if(!is_running) {
LOGE("No open device.");
return;
}
mbtk_audio_pcm_recorder_stop();
}
//
// Function: Ql_AudRecorder_Close
//
// Description:
// Close recorder, and free the resource
void Ql_AudRecorder_Close(void)
{
if(!is_running) {
LOGE("No open device.");
return;
}
is_running = 0;
mbtk_audio_pcm_deinit();
}
//
// Function: Ql_clt_set_mixer_value
//
// Description:
// Close recorder, and free the resource
boolean Ql_clt_set_mixer_value(const char *device, int count, const char *value)
{
return FALSE;
}
int Ql_AudTone_Open(char* device, _cb_onPlayer cb)//cb not support now
{
return 0;
}
int Ql_AudTone_Start(int hdl, struct Ql_TonePara *para)
{
return 0;
}
void Ql_AudTone_Stop(int hdl)
{
}
void Ql_AudTone_Close(int hdl)
{
}
//****************QL Codec API************************//
//
// Function: Ql_AudCodec_Set_ALC5616_DRCAGC
//
// Description:
// Set ALC5616 DRC/AGC configuration
int Ql_AudCodec_Set_ALC5616_DRCAGC(const char *i2c, struct Ql_ALC5616_DRCAGC *cfg)
{
return 0;
}
//
// Function: Ql_Update_wav_size
//
// Description:
// update wav format file size in the header
// @param fd:
// wav file discriptor
// @param size:
// wav file size to update
int Ql_Update_wav_size(int fd, int size)
{
return 0;
}
//add by grady, 2018-5-29
/*
* describe : this function is use to open pcm device
* paras :
* device : this should be fix to hw:0,0
* flags ; pcm play flags
* rate: sample rate
* channels : audio channal 1 or 2
* format: format to play or record, 16bit line,MP3
* hostless: if there is no file it is true
* return :
* pcm : pcm handle, use can use this handle to read write data
*/
struct pcm *quec_pcm_open(char *device, unsigned flags, unsigned rate, unsigned channels, unsigned format, unsigned hostless)
{
return NULL;
}
/*
* describe : this function is use to close pcm handle
* paras :
* pcm : pcm handle to close
* return :
*/
int quec_pcm_close(struct pcm *pcm )
{
return 0;
}
/*
* describe : this function is use to read pcm buffer
* paras :
* pcm : pcm handle to write date
* buffer: data buffer
* lenth: data length
* return :
*/
int quec_read_pcm(struct pcm *pcm, void * buffer, int length)
{
return 0;
}
/*
* describe : this function is use to get pcm buffer lenth
* paras :
* lenth: data length
* return
* buffer length
*/
int quec_get_pem_buffer_len(struct pcm *pcm)
{
return 0;
}
void dtmf_cb1(char dtmf)
{
printf("%s:%c\n", __FUNCTION__, dtmf);
}
/**
* @brief Set RX DSP Gain
* @details
* Gain support [-36,12] dB
*
* @param gain
* DSP gain
*/
int Ql_Rxgain_Set(int value)
{
#ifdef MBTK_AF_SUPPORT
int volume =0;
if(value < -36 || value > 13)
{
volume = 0;
}
else
{
volume = value;
}
if(player_hdl==NULL)
return 0;
char databuf[1025]={0};
memcpy(databuf, " ", 1024);
mbtk_audio_play_stream_new(player_hdl, databuf, 1024, volume);
return 0;
#else
mbtk_dsp_gain_set(1, value);
return 0;
#endif
return 0;
}
/** Ql_Playback_Samprate_Set
* @brief Set Playback PCM Samprate
* @details
* 0 for NB 1 for WB
*
* @param samprate
* samprate for PCM playback,default value is PCM NB
*/
int Ql_Playback_Samprate_Set(int samprate)
{
printf("samprate is %d \n",samprate);
if(samprate == 1)
{
sample_rate = 16000;
mbtk_audio_pcm_sample_rate_set(MBTK_AUDIO_SAMPLE_RATE_16000);
}
else{
mbtk_audio_pcm_sample_rate_set(MBTK_AUDIO_SAMPLE_RATE_8000);
sample_rate = 8000;
}
return 0;
}
int Ql_Mp3_To_Wav(const char *wavpath, char *mp3path)
{
return 0;
}
int Ql_Mp3_To_Play(char *mp3path, int hdl,int sample_rate)
{
return 0;
}
//add by grady, 2018-6-2
/*
* describe : this function is use to open mixer device
* paras :
* device: mixer device
* return
* mixer handle
*/
struct mixer *quec_mixer_open(const char *device)
{
return NULL;
}
/*
* describe : this function is use to close mixer device
* paras :
* mixer: mixer handle
* return
* none
*/
void quec_mixer_close(struct mixer *mixer)
{
}
/*
* describe : this function is use to get mixer devie control
* paras :
* mixer: mixer handle
* name: mixer device
* index: mixer index
* return
* mixer control
*/
struct mixer_ctl *quec_mixer_get_control(struct mixer *mixer, const char *name, unsigned index)
{
return NULL;
}
/*
* describe : this function is use to set mulvalues
* paras :
* mixer: mixer handle
* count: count
* argv: data
* return :
*
*/
int quec_mixer_ctl_mulvalues(struct mixer_ctl *ctl, int count, char ** argv)
{
return 0;
}
//end grady
/*****************************************************************
* Function: Ql_AudPlayer_OpenExt
*
* Description:
* expend function from Ql_AudPlayer_OpenExt
* Open audio play device, and specify the callback function.
* This function can be called twice to play different audio sources.
*
* Parameters:
* device : a string that specifies the PCM device.
* NULL, means the audio will be played on the default PCM device.
*
* If you want to mixedly play audio sources, you can call this
* API twice with specifying different PCM device.
* The string devices available:
* "hw:0,0" (the default play device)
* "hw:0,13" (this device can mix audio and TTS)
* "hw:0,14"
*
* cb_func : callback function for audio player.
* The results of all operations on audio player
* are informed in callback function.
*
* flags : pcm flags, eg: PCM_MMAP, PCM_NMMAP.
*
* channels: pcm sample channels.
*
* rate : pcm sample rate.
*
* format : pcm sample fromat
*
* Return:
* pcm device handle
* NULL, fail
*****************************************************************/
int Ql_AudPlayer_OpenExt(
char *dev,
_cb_onPlayer cb_fun,
int flags,
int channels,
int rate,
int format)
{
return 0;
}
/*****************************************************************
* Function: Ql_AudRecorder_Open
*
* Description:
* Open audio record device, and specify the callback function.
*
* Parameters:
* device : not used. MUST be NULL.
*
* cb_func : callback function for audio player.
* The results of all operations on audio recorder
* are informed in callback function.
*
* flags : pcm flags, eg: PCM_MMAP, PCM_NMMAP.
*
* channels: pcm sample channels.
*
* rate : pcm sample rate.
*
* format : pcm sample fromat
*
* Return:
* pcm device handle
* NULL, fail
*****************************************************************/
int Ql_AudRecorder_OpenExt(
char *dev,
_cb_onRecorder cb_fun,
int flags,
int channels,
int rate,
int format)
{
return 0;
}
/*
* Function: uac enable
*
* Description:
* uac enable
*
* Parameters:
* none
* Return:
* TURE or FALSE
*/
int ql_uac_enable(void)
{
return 0;
}
/*
* Function: uac disable
*
* Description:
* uac disable
*
* Parameters:
* none
* Return:
* TURE or FALSE
*/
int ql_uac_disable(void)
{
return 0;
}