281 lines
5.9 KiB
C++
281 lines
5.9 KiB
C++
#define __MAKE_PLUGIN__
|
|
|
|
#include<hgl/plugin/PlugIn.h>
|
|
#include<hgl/plugin/PlugInInterface.h>
|
|
#include<malloc.h>
|
|
#include<string.h>
|
|
#include<hgl/al/al.h>
|
|
|
|
#include<opusfile.h>
|
|
|
|
using namespace hgl;
|
|
using namespace openal;
|
|
|
|
ALvoid LoadOpus(ALbyte *memory, ALsizei memory_size,ALenum *format, ALvoid **data, ALsizei *size, ALsizei *freq, ALboolean *loop)
|
|
{
|
|
OggOpusFile *of;
|
|
|
|
int op_error;
|
|
|
|
of=op_open_memory((const unsigned char *)memory,memory_size,&op_error);
|
|
|
|
if(!of)
|
|
return;
|
|
|
|
const OpusHead *head=op_head(of,0);
|
|
|
|
if(head->channel_count==1)*format=AL_FORMAT_MONO16;else
|
|
if(head->channel_count==2)*format=AL_FORMAT_STEREO16;else
|
|
return;
|
|
|
|
long pcm_total=op_pcm_total(of,-1)*head->channel_count;
|
|
|
|
opus_int16 *out_buf=new opus_int16[pcm_total];
|
|
int out_size;
|
|
int out_total_size=0;
|
|
|
|
while(-1)
|
|
{
|
|
out_size=op_read(of,out_buf+out_total_size,pcm_total-out_total_size,nullptr);
|
|
|
|
if(out_size<=0)
|
|
break;
|
|
|
|
out_total_size+=out_size*head->channel_count;
|
|
}
|
|
|
|
*freq=head->input_sample_rate;
|
|
*size=out_total_size*2;
|
|
*data=out_buf;
|
|
}
|
|
|
|
void ClearOpus(ALenum,ALvoid *data,ALsizei,ALsizei)
|
|
{
|
|
opus_int16 *pcm=(opus_int16 *)data;
|
|
|
|
delete[] pcm;
|
|
}
|
|
|
|
|
|
ALvoid LoadOpusFloat32(ALbyte *memory, ALsizei memory_size,ALenum *format, float **data, ALsizei *size, ALsizei *freq, ALboolean *loop)
|
|
{
|
|
OggOpusFile *of;
|
|
|
|
int op_error;
|
|
|
|
of=op_open_memory((const unsigned char *)memory,memory_size,&op_error);
|
|
|
|
if(!of)
|
|
return;
|
|
|
|
const OpusHead *head=op_head(of,0);
|
|
|
|
if(head->channel_count==1)*format=AL_FORMAT_MONO_FLOAT32;else
|
|
if(head->channel_count==2)*format=AL_FORMAT_STEREO_FLOAT32;else
|
|
return;
|
|
|
|
long pcm_total=op_pcm_total(of,-1)*head->channel_count;
|
|
|
|
float *out_buf=new float[pcm_total];
|
|
int out_size;
|
|
int out_total_size=0;
|
|
|
|
while(-1)
|
|
{
|
|
out_size=op_read_float(of,out_buf+out_total_size,pcm_total-out_total_size,nullptr);
|
|
|
|
if(out_size<=0)
|
|
break;
|
|
|
|
out_total_size+=out_size*head->channel_count;
|
|
}
|
|
|
|
*freq=head->input_sample_rate;
|
|
*size=out_total_size*sizeof(float);
|
|
*data=out_buf;
|
|
}
|
|
|
|
void ClearOpusFloat32(ALenum,float *data,ALsizei,ALsizei)
|
|
{
|
|
delete[] data;
|
|
}
|
|
|
|
struct OpusStream
|
|
{
|
|
OggOpusFile *of;
|
|
const OpusHead *head;
|
|
};
|
|
|
|
void *OpenOpus(ALbyte *memory,ALsizei memory_size,ALenum *format,ALsizei *freq,double *total_time)
|
|
{
|
|
OggOpusFile *of;
|
|
|
|
int op_error;
|
|
|
|
of=op_open_memory((const unsigned char *)memory,memory_size,&op_error);
|
|
|
|
if(!of)
|
|
return(nullptr);
|
|
|
|
const OpusHead *head=op_head(of,0);
|
|
|
|
if(head->channel_count==1)*format=AL_FORMAT_MONO16;else
|
|
if(head->channel_count==2)*format=AL_FORMAT_STEREO16;else
|
|
return(nullptr);
|
|
|
|
*freq=head->input_sample_rate;
|
|
|
|
*total_time=double(op_pcm_total(of,-1))/double(head->input_sample_rate);
|
|
|
|
OpusStream *os=new OpusStream;
|
|
|
|
os->of=of;
|
|
os->head=head;
|
|
|
|
return os;
|
|
}
|
|
|
|
void CloseOpus(void *ptr)
|
|
{
|
|
OpusStream *os=(OpusStream *)ptr;
|
|
|
|
op_free(os->of);
|
|
|
|
delete os;
|
|
}
|
|
|
|
uint ReadOpus(void *ptr,char *data,uint buf_max)
|
|
{
|
|
OpusStream *os=(OpusStream *)ptr;
|
|
int result;
|
|
uint size=0;
|
|
uint buf_left=buf_max/2; //16位,所以要除2
|
|
|
|
while(size<buf_max)
|
|
{
|
|
result=op_read(os->of,((opus_int16 *)data)+size,buf_left-size,nullptr);
|
|
|
|
if(result>0)size+=result*os->head->channel_count;else
|
|
if(result<=0)break;
|
|
}
|
|
|
|
return(size*2);
|
|
}
|
|
|
|
uint ReadOpusFloat32(void *ptr,float *data,uint buf_max)
|
|
{
|
|
OpusStream *os=(OpusStream *)ptr;
|
|
int result;
|
|
uint size=0;
|
|
uint buf_left=buf_max/sizeof(float);
|
|
|
|
while(size<buf_max)
|
|
{
|
|
result=op_read_float(os->of,data+size,buf_left-size,nullptr);
|
|
|
|
if(result>0)size+=result*os->head->channel_count;else
|
|
if(result<=0)break;
|
|
}
|
|
|
|
return(size*sizeof(float));
|
|
}
|
|
|
|
void RestartOpus(void *ptr)
|
|
{
|
|
OpusStream *os=(OpusStream *)ptr;
|
|
|
|
op_pcm_seek(os->of,0);
|
|
}
|
|
//--------------------------------------------------------------------------------------------------
|
|
struct OutInterface2
|
|
{
|
|
void (*Load)(ALbyte *,ALsizei,ALenum *,ALvoid **,ALsizei *,ALsizei *,ALboolean *);
|
|
void (*Clear)(ALenum,ALvoid *,ALsizei,ALsizei);
|
|
|
|
void *(*Open)(ALbyte *,ALsizei,ALenum *,ALsizei *,double *);
|
|
void (*Close)(void *);
|
|
uint (*Read)(void *,char *,uint);
|
|
void (*Restart)(void *);
|
|
};
|
|
|
|
static OutInterface2 out_interface_2=
|
|
{
|
|
LoadOpus,
|
|
ClearOpus,
|
|
|
|
OpenOpus,
|
|
CloseOpus,
|
|
ReadOpus,
|
|
RestartOpus
|
|
};
|
|
|
|
struct OutInterface3
|
|
{
|
|
void (*Load)(ALbyte *,ALsizei,ALenum *,float **,ALsizei *,ALsizei *,ALboolean *);
|
|
void (*Clear)(ALenum,float *,ALsizei,ALsizei);
|
|
|
|
uint (*Read)(void *,float *,uint);
|
|
};
|
|
|
|
static OutInterface3 out_interface_3
|
|
{
|
|
LoadOpusFloat32,
|
|
ClearOpusFloat32,
|
|
|
|
ReadOpusFloat32
|
|
};
|
|
//--------------------------------------------------------------------------------------------------
|
|
#if HGL_OS != HGL_OS_Windows
|
|
const u16char plugin_intro[]=U16_TEXT("Opus 音频文件解码(使用操作系统内置解码器,2016-09-16)");
|
|
#else
|
|
const u16char plugin_intro[]=U16_TEXT("Opus 音频文件解码(LibOpus 1.1.3,LibOpusFile 0.7,LibOGG 1.3.2,2016-09-16)");
|
|
#endif//
|
|
|
|
uint32 GetPlugInVersion()
|
|
{
|
|
return(3); //版本号
|
|
//根据版本号取得不同的API
|
|
}
|
|
|
|
u16char * GetPlugInIntro()
|
|
{
|
|
return((u16char *)plugin_intro);
|
|
}
|
|
|
|
bool GetPlugInInterface(uint32 ver,void *data)
|
|
{
|
|
if(ver==2)
|
|
{
|
|
memcpy(data,&out_interface_2,sizeof(OutInterface2));
|
|
}
|
|
else
|
|
if(ver==3)
|
|
{
|
|
memcpy(data,&out_interface_3,sizeof(OutInterface3));
|
|
}
|
|
else
|
|
return(false);
|
|
|
|
return(true);
|
|
}
|
|
|
|
static PlugInInterface pii=
|
|
{
|
|
nullptr,
|
|
|
|
GetPlugInVersion,
|
|
GetPlugInIntro,
|
|
|
|
GetPlugInInterface,
|
|
nullptr,
|
|
|
|
nullptr,
|
|
nullptr
|
|
};
|
|
|
|
HGL_PLUGIN_FUNC PlugInInterface *InitPlugIn()
|
|
{
|
|
return &pii;
|
|
}
|
|
//--------------------------------------------------------------------------------------------------
|