|
|
#include "JZsdkLib.h"
|
|
|
|
|
|
#include "../../Megaphone.h"
|
|
|
#include "../Megaphone_Opus.h"
|
|
|
#include "version_choose.h"
|
|
|
#include "BaseConfig.h"
|
|
|
|
|
|
#include "AudioDeal/AudioDeal.h"
|
|
|
|
|
|
#include "opus.h"
|
|
|
|
|
|
#define OPUS_MAX_FRAME_SIZE (6 * 960)
|
|
|
#define OPUS_CHANNELS (1)
|
|
|
#define OPUS_MAX_PACKET_SIZE (3 * 1276)
|
|
|
|
|
|
#define PCM_PLAY_FILE_NAME "/root/test_audio.pcm" //用于播放的pcm
|
|
|
|
|
|
#define PCM_RATE 16000 //解码得到的pcm码率 目前仅支持16000码率
|
|
|
static int g_opus_decodeBitrate = 16000; //解码码率
|
|
|
|
|
|
static int g_Opus_play_Flag = JZ_FLAGCODE_OFF; //opus的播放标志位
|
|
|
static int g_Opus_decode_Flag = JZ_FLAGCODE_OFF; //opus的解码标志位
|
|
|
static T_JZTaskHandle g_DecodeOpus_task = NULL;
|
|
|
static T_JZTaskHandle g_OpusPlay_task = NULL;
|
|
|
|
|
|
/***************************************************************************************************************
|
|
|
*
|
|
|
* 播放部分
|
|
|
*
|
|
|
*
|
|
|
****************************************************************************************************************/
|
|
|
|
|
|
|
|
|
static T_JZsdkReturnCode FixedFilePlay()
|
|
|
{
|
|
|
FILE *PlayFixedFile_pcm_fp = NULL;
|
|
|
unsigned int nbBytes;
|
|
|
uint8_t cbits[3 * 1276];
|
|
|
int timeNum = 0;
|
|
|
int loop = JZ_FLAGCODE_OFF;
|
|
|
int loop_interval;
|
|
|
|
|
|
if(g_Opus_decode_Flag != JZ_FLAGCODE_OFF)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("opus解码超时,无法播放");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
g_Opus_play_Flag = JZ_FLAGCODE_ON;
|
|
|
|
|
|
JZSDK_LOG_INFO("播放指定位置的opus pcm文件\n");
|
|
|
PlayFixedFile_pcm_fp = fopen(PCM_PLAY_FILE_NAME, "r");
|
|
|
if (PlayFixedFile_pcm_fp == NULL)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("打开固定opus pcm文件失败\n");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
// 将文件指针移动到文件开头
|
|
|
if (fseek(PlayFixedFile_pcm_fp, 0, SEEK_SET) != 0)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("Failed to move file pointer to the beginning of the file");
|
|
|
fclose(PlayFixedFile_pcm_fp);
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
while (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_ON)
|
|
|
{
|
|
|
nbBytes = fread(cbits, 1, 3 * 1276, PlayFixedFile_pcm_fp);
|
|
|
if(nbBytes > 0)
|
|
|
{
|
|
|
AudioDeal_PcmDataInput(PCM_RATE, (unsigned char *)cbits, nbBytes);
|
|
|
}
|
|
|
if (feof(PlayFixedFile_pcm_fp))
|
|
|
{
|
|
|
//如果循环播放没打开
|
|
|
Megaphone_param(JZ_FLAGCODE_GET, MEGAPHONE_LOOP, &loop);
|
|
|
Megaphone_param(JZ_FLAGCODE_GET, MEGAPHONE_LOOP_INTERVAL, &loop_interval);
|
|
|
|
|
|
if (loop == JZ_FLAGCODE_OFF)
|
|
|
{
|
|
|
timeNum = 0;
|
|
|
|
|
|
// //播放结束延迟
|
|
|
// while ((timeNum <=3000) && (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_ON))
|
|
|
// {
|
|
|
// delayMs(10);
|
|
|
// timeNum +=10;
|
|
|
// }
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
//如果循环播放打开
|
|
|
else if (loop == JZ_FLAGCODE_ON)
|
|
|
{
|
|
|
timeNum = 0;
|
|
|
JZSDK_LOG_INFO("循环播放opus");
|
|
|
|
|
|
// //播放结束延迟
|
|
|
// while ((loop == 1) && (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_ON))
|
|
|
// {
|
|
|
// delayMs(10);
|
|
|
// timeNum +=10;
|
|
|
// }
|
|
|
|
|
|
//重置文件光标 继续播放
|
|
|
fseek(PlayFixedFile_pcm_fp, 0, SEEK_SET);
|
|
|
|
|
|
//循环播放延时
|
|
|
while (loop_interval > 0 && (loop == JZ_FLAGCODE_ON) && (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_ON))
|
|
|
{
|
|
|
delayMs(50);
|
|
|
loop_interval -= 50;
|
|
|
}
|
|
|
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
fclose(PlayFixedFile_pcm_fp);
|
|
|
|
|
|
g_Opus_play_Flag = JZ_FLAGCODE_OFF;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
*
|
|
|
* 播放固定位置pcm线程
|
|
|
*
|
|
|
*/
|
|
|
static void *PlayFixedFile_task(void *arg)
|
|
|
{
|
|
|
Megaphone_MegDataGenFlag(JZ_FLAGCODE_SET, JZ_FLAGCODE_ON);
|
|
|
Megaphone_MegDataGenFinshFlag(JZ_FLAGCODE_SET, JZ_FLAGCODE_ON);
|
|
|
|
|
|
//广播开始
|
|
|
Megaphone_status_Broadcast(AUDIO_PLAY_STATUS_OPUS_RECORD);
|
|
|
|
|
|
int amplifier = JZ_FLAGCODE_ON;
|
|
|
Megaphone_Amplifier_param(JZ_FLAGCODE_SET, &lifier);
|
|
|
|
|
|
FixedFilePlay();
|
|
|
|
|
|
amplifier = JZ_FLAGCODE_OFF;
|
|
|
Megaphone_Amplifier_param(JZ_FLAGCODE_SET, &lifier);
|
|
|
|
|
|
Megaphone_MegDataGenFlag(JZ_FLAGCODE_SET, JZ_FLAGCODE_OFF);
|
|
|
Megaphone_MegDataGenFinshFlag(JZ_FLAGCODE_SET, JZ_FLAGCODE_OFF);
|
|
|
|
|
|
//广播关闭
|
|
|
Megaphone_status_Broadcast(JZ_FLAGCODE_OFF);
|
|
|
}
|
|
|
|
|
|
/*******************************
|
|
|
*
|
|
|
* 播放规定位置的opus文件
|
|
|
* 旧接口,无需定位传入的位置
|
|
|
*
|
|
|
************************************/
|
|
|
T_JZsdkReturnCode OpusFile_PlayFixedFile()
|
|
|
{
|
|
|
T_JZsdkOsalHandler *OsalHandler = JZsdk_Platform_GetOsalHandler();
|
|
|
|
|
|
OsalHandler->TaskCreate("PiayFilexdFile", PlayFixedFile_task, 8192, NULL, &g_DecodeOpus_task);
|
|
|
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************************************************/
|
|
|
|
|
|
/*
|
|
|
|
|
|
解码函数
|
|
|
|
|
|
|
|
|
*/
|
|
|
static T_JZsdkReturnCode OpusDecodeFun(unsigned char *OpusFile)
|
|
|
{
|
|
|
FILE *fin = NULL;
|
|
|
FILE *fout = NULL;
|
|
|
OpusDecoder *decoder;
|
|
|
opus_int16 out[OPUS_MAX_FRAME_SIZE * OPUS_CHANNELS];
|
|
|
uint8_t cbits[OPUS_MAX_PACKET_SIZE];
|
|
|
int32_t nbBytes;
|
|
|
int32_t err;
|
|
|
|
|
|
if (g_Opus_decode_Flag != JZ_FLAGCODE_OFF)
|
|
|
{
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
g_Opus_decode_Flag = JZ_FLAGCODE_ON;
|
|
|
|
|
|
printf("Decode Start 解码开始\n"); //解码开始
|
|
|
|
|
|
//打开解码的opus文件
|
|
|
//TODO: need delete
|
|
|
//attention: you can use "ffmpeg -i xxx.mp3 -ar 16000 -ac 1 out.wav" and "./test_opus_tool out.wav out.opus" to generate opus file to test
|
|
|
fin = fopen(OpusFile, "r");
|
|
|
if (fin == NULL) {
|
|
|
JZSDK_LOG_ERROR("fin打开失败");
|
|
|
goto DecodeFinsh;
|
|
|
}
|
|
|
|
|
|
//创建一个解码器
|
|
|
decoder = opus_decoder_create(PCM_RATE, OPUS_CHANNELS, &err);
|
|
|
if (err < 0) {
|
|
|
JZSDK_LOG_ERROR("解码器创建失败 %s",opus_strerror(err));
|
|
|
goto DecodeFinsh;
|
|
|
}
|
|
|
|
|
|
//创建一个opus输出文件
|
|
|
fout = fopen(PCM_PLAY_FILE_NAME, "w");
|
|
|
if (fout == NULL) {
|
|
|
JZSDK_LOG_ERROR("创建opus输出文件失败");
|
|
|
goto DecodeFinsh;
|
|
|
}
|
|
|
|
|
|
printf("opus解码初始化完成\n");
|
|
|
|
|
|
int frame_size;
|
|
|
|
|
|
while (1)
|
|
|
{
|
|
|
int i;
|
|
|
opus_int16 TempPcm[OPUS_MAX_FRAME_SIZE * OPUS_CHANNELS];
|
|
|
|
|
|
frame_size = 0;
|
|
|
|
|
|
//读取opus内容
|
|
|
/* Read a 16 bits/sample audio frame. */
|
|
|
nbBytes = fread(cbits, 1, g_opus_decodeBitrate / 8000 * 40, fin);
|
|
|
if (feof(fin))
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
printf("fread nbBytes=%d\n",nbBytes);
|
|
|
//printf("s_decodeBitrate=%d",s_decodeBitrate / OPUS_DECODE_BITRATE_8KBPS * OPUS_DECODE_FRAME_SIZE_8KBPS);
|
|
|
/* Decode the data. In this example, frame_size will be constant because
|
|
|
the encoder is using a constant frame size. However, that may not
|
|
|
be the case for all encoders, so the decoder must always check
|
|
|
the frame size returned. */
|
|
|
|
|
|
//向解码器输入opus内容
|
|
|
frame_size = opus_decode(decoder, cbits, nbBytes, out, OPUS_MAX_FRAME_SIZE, 0);
|
|
|
if (frame_size < 0) {
|
|
|
JZSDK_LOG_ERROR("decoder failed: %s",opus_strerror(frame_size));
|
|
|
goto DecodeFinsh;
|
|
|
}
|
|
|
|
|
|
//解码完成
|
|
|
printf("decode data to file: %d\r\n", frame_size * OPUS_CHANNELS);
|
|
|
/* Convert to little-endian ordering. */
|
|
|
|
|
|
for (i = 0; i < OPUS_CHANNELS * frame_size; i++) {
|
|
|
TempPcm [i] = out[i] & 0xFF | (out[i] >> 8) << 8;
|
|
|
//TempPcm[i] = PcmNoiseReduction(TempPcm[i]);
|
|
|
}
|
|
|
|
|
|
fwrite(TempPcm, sizeof(short), frame_size * OPUS_CHANNELS, fout);
|
|
|
|
|
|
}
|
|
|
|
|
|
DecodeFinsh:
|
|
|
|
|
|
//释放解码器
|
|
|
if (decoder != NULL)
|
|
|
{
|
|
|
opus_decoder_destroy(decoder);
|
|
|
printf("opus_decoder_destroy(decoder)\n");
|
|
|
}
|
|
|
|
|
|
//关闭文件
|
|
|
if (fin != NULL)
|
|
|
{
|
|
|
fclose(fin);
|
|
|
fin = NULL;
|
|
|
printf("fclose(fin);\n");
|
|
|
}
|
|
|
|
|
|
//关闭文件
|
|
|
if (fout != NULL)
|
|
|
{
|
|
|
fclose(fout);
|
|
|
fout = NULL;
|
|
|
printf("fclose(fout);\n");
|
|
|
}
|
|
|
|
|
|
if (frame_size < 0)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("opus解码失败");
|
|
|
g_Opus_decode_Flag = JZ_FLAGCODE_OFF;
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
//解码完成
|
|
|
JZSDK_LOG_INFO("Decode Finished...\n");
|
|
|
g_Opus_decode_Flag = JZ_FLAGCODE_OFF;
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/*******************
|
|
|
*
|
|
|
* opus解码线程
|
|
|
*
|
|
|
*******************/
|
|
|
static void *DecodeOpus_task(void *arg)
|
|
|
{
|
|
|
unsigned char *opusFile = (unsigned char *)arg;
|
|
|
|
|
|
T_JZsdkReturnCode ret = OpusDecodeFun(opusFile);
|
|
|
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
|
|
|
{
|
|
|
//广播解码失败
|
|
|
Megaphone_Broadcast_OpusDecodeStatus(1);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
Megaphone_Broadcast_OpusDecodeStatus(0);
|
|
|
}
|
|
|
|
|
|
free(opusFile);
|
|
|
}
|
|
|
|
|
|
T_JZsdkReturnCode OpusFile_DecodeOpus(unsigned char *opusFile)
|
|
|
{
|
|
|
T_JZsdkOsalHandler *OsalHandler = JZsdk_Platform_GetOsalHandler();
|
|
|
|
|
|
T_JZsdkReturnCode ret = JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
|
|
|
|
|
//因为播放的流通pcm文件只有一份,所以播放时,不能进行解码,不然会导致相当多问题
|
|
|
int i = 0;
|
|
|
while (i <= 4 && g_Opus_play_Flag == JZ_FLAGCODE_ON)
|
|
|
{
|
|
|
i++;
|
|
|
delayMs(50);
|
|
|
}
|
|
|
|
|
|
//判断上一次播放是否结束 判断解码是否完成
|
|
|
if(i == 4)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("超时200ms,上一次opus录音播放未结束,无法解码");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
i = 0;
|
|
|
while (i<=4 && g_Opus_decode_Flag == JZ_FLAGCODE_ON)
|
|
|
{
|
|
|
i++;
|
|
|
delayMs(50);
|
|
|
}
|
|
|
if(i == 4)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("超时,上一次opus仍在解码,无法开始新的解码");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
unsigned char *DecodeFile = OsalHandler->Malloc(strlen(opusFile));
|
|
|
if(DecodeFile == NULL)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("DecodeFile malloc failed");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_MEMORY_ALLOC_FAILED;
|
|
|
}
|
|
|
memset(DecodeFile, strlen(opusFile), 0);
|
|
|
memcpy(DecodeFile, opusFile, strlen(opusFile));
|
|
|
|
|
|
OsalHandler->TaskCreate("DecodeOpus", DecodeOpus_task((void *)DecodeFile), 8192,NULL, &g_DecodeOpus_task);
|
|
|
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
|
|
} |
|
|
\ No newline at end of file |
...
|
...
|
|