CMAudio/src/AudioPlayer.cpp

562 lines
13 KiB
C++
Raw Normal View History

2020-06-18 03:38:48 +08:00
#include<hgl/audio/AudioPlayer.h>
#include<hgl/log/LogInfo.h>
#include<hgl/plugin/PlugIn.h>
2020-06-18 03:38:48 +08:00
#include<hgl/Time.h>
#include<hgl/io/MemoryInputStream.h>
#include<hgl/io/FileInputStream.h>
2020-06-18 03:38:48 +08:00
#include"AudioDecode.h"
namespace hgl
{
const os_char *GetAudioDecodeName(const AudioFileType aft);
void AudioPlayer::InitPrivate()
{
if(!alGenSources)
{
LOG_ERROR(OS_TEXT("OpenAL/EE 还未初始化!"));
return;
}
auto_gain.open=false;
audio_ptr=nullptr;
audio_data=nullptr;
audio_data_size=0;
audio_buffer=nullptr;
audio_buffer_size=0;
decode=nullptr;
ps=PlayState::None;
2020-06-18 03:38:48 +08:00
total_time=0;
2020-06-18 03:38:48 +08:00
if(!audiosource.Create())return;
audiosource.SetLoop(false);
2020-06-18 03:38:48 +08:00
source=audiosource.index;
alGenBuffers(3,buffer);
}
AudioPlayer::AudioPlayer()
{
InitPrivate();
}
AudioPlayer::AudioPlayer(const os_char *filename,AudioFileType aft)
{
InitPrivate();
if(filename)
Load(filename,aft);
}
AudioPlayer::AudioPlayer(InputStream *stream,int size,AudioFileType aft)
{
InitPrivate();
Load(stream,size,aft);
}
// AudioPlayer::AudioPlayer(HAC *hac,const os_char *filename,AudioFileType aft)
// {
// InitPrivate();
//
// Load(hac,filename,aft);
// }
AudioPlayer::~AudioPlayer()
{
SAFE_CLEAR(decode);
2020-06-18 03:38:48 +08:00
if(!audio_data)return;
Clear();
alDeleteBuffers(3,buffer);
SAFE_CLEAR_ARRAY(audio_buffer);
}
bool AudioPlayer::Load(AudioFileType aft)
{
const os_char *plugin_name=GetAudioDecodeName(aft);
if(!plugin_name)return(false);
decode=new AudioPlugInInterface;
2020-06-18 03:38:48 +08:00
if (!GetAudioInterface(plugin_name, decode, nullptr))
2020-06-18 03:38:48 +08:00
{
delete decode;
decode=nullptr;
LOG_ERROR(OS_TEXT("无法加载音频解码插件:")+OSString(plugin_name));
return(false);
}
{
audio_ptr=decode->Open(audio_data,audio_data_size,&format,&rate,&total_time);
2020-06-18 03:38:48 +08:00
audio_buffer_size=(AudioTime(format,rate)+9)/10; // 1/10 秒
if(audio_buffer)
delete[] audio_buffer;
audio_buffer=new char[audio_buffer_size];
wait_time=0.1;
if(wait_time>total_time/3.0f)
wait_time=total_time/10.0f;
2020-06-18 03:38:48 +08:00
return(true);
}
}
/**
* ,OGG
* @param stream
* @param size
* @param aft
* @return
*/
bool AudioPlayer::Load(InputStream *stream,int size,AudioFileType aft)
{
if(!alGenBuffers)return(false);
if(!stream)return(false);
if(size<=0)return(false);
Clear();
if(!RangeCheck(aft))
2020-06-18 03:38:48 +08:00
{
LOG_ERROR(OS_TEXT("未支持的音频文件类型AudioFileType: ")+OSString::valueOf((int)aft));
2020-06-18 03:38:48 +08:00
return(false);
}
else
{
audio_data=new ALbyte[size];
stream->Read(audio_data,size);
audio_data_size=size;
return Load(aft);
}
}
/**
*
* @param filename
* @param aft
* @return
*/
bool AudioPlayer::Load(const os_char *filename,AudioFileType aft)
{
if(!alGenBuffers)return(false);
if(!filename||!(*filename))return(false);
if(!RangeCheck(aft))
2020-06-18 03:38:48 +08:00
aft=CheckAudioFileType(filename);
if(!RangeCheck(aft))
2020-06-18 03:38:48 +08:00
{
LOG_ERROR(OS_TEXT("未知的音频文件类型AudioFile: ")+OSString(filename));
return(false);
}
OpenFileInputStream fis(filename);
return(Load(fis,fis->Available(),aft));
}
// /**
// * 从文件中加载一段音频数据
// * @param hac HAC包指针
// * @param filename 音频文件名称
// * @param aft 音频文件类型
// * @return 是否加载成功
// */
// bool AudioPlayer::Load(HAC *hac,const os_char *filename,AudioFileType aft)
// {
// if(!alGenBuffers)return(false);
//
// os_char *ext;
// Stream *stream;
// bool result;
//
// ext=strrchr(filename,u'.');
//
// LowerString(ext);
//
// if(aft<=aftNone||aft>=aftEnd)
// {
// if(strcmp(ext,u".ogg")==0)aft=aftOGG;else
// {
// PutError(u"未支持的音频文件类型AudioFileType:%d",aft);
// return(false);
// }
// }
//
// stream=hac->LoadFile(filename);
//
// if(stream)
// {
// result=Load(stream,aft);
//
// delete stream;
//
// return(result);
// }
//
// return(false);
// }
void AudioPlayer::Clear()
{
Stop();
if(decode&&audio_ptr)
decode->Close(audio_ptr);
SAFE_CLEAR_ARRAY(audio_data);
SAFE_CLEAR_ARRAY(audio_buffer);
audio_ptr=nullptr;
total_time=0;
2020-06-18 03:38:48 +08:00
}
bool AudioPlayer::IsLoop()
2020-06-18 03:38:48 +08:00
{
lock.Lock();
bool rv=loop;
lock.Unlock();
return(rv);
}
void AudioPlayer::SetLoop(bool val)
{
lock.Lock();
loop=val;
lock.Unlock();
}
bool AudioPlayer::ReadData(ALuint n)
{
if(!decode)return(false);
2020-06-18 03:38:48 +08:00
uint size;
size=decode->Read(audio_ptr,audio_buffer,audio_buffer_size);
if(size)
{
alBufferData(n,format,audio_buffer,size,rate);
if(alLastError())return(false);
return(true);
}
return(false);
}
bool AudioPlayer::Playback()
{
if(!audio_data)return(false);
if(!decode)return(false);
2020-06-18 03:38:48 +08:00
alSourceStop(source);
ClearBuffer();
decode->Restart(audio_ptr);
int count=0;
audio_buffer_count=0;
if(ReadData(buffer[0]))
{
count++;
if(ReadData(buffer[1])) //以免有些音效太短,在这里直接失败
count++;
if(ReadData(buffer[2])) //以免有些音效太短,在这里直接失败
count++;
alSourceQueueBuffers(source,count,buffer);
alSourcePlay(source);
start_time=GetDoubleTime();
ps=PlayState::Play;
2020-06-18 03:38:48 +08:00
return(true);
}
else
{
ps=PlayState::Exit;
2020-06-18 03:38:48 +08:00
return(false);
}
}
/**
*
* @param _loop
*/
void AudioPlayer::Play(bool _loop)
{
if(!audio_data)return;
lock.Lock();
loop=_loop;
if(ps==PlayState::None||ps==PlayState::Pause) //未启动线程
2020-06-18 03:38:48 +08:00
Start();
Playback(); //Execute执行有检测Lock所以不必担心该操作会引起线程冲突
lock.Unlock();
}
/**
*
*/
void AudioPlayer::Stop()
{
if(!audio_data)return;
bool thread_is_live=true;
lock.Lock();
if(Thread::IsLive())
ps=PlayState::Exit;
2020-06-18 03:38:48 +08:00
else
thread_is_live=false;
lock.Unlock();
if(thread_is_live)
Thread::WaitExit();
ps=PlayState::None;
2020-06-18 03:38:48 +08:00
}
/**
*
*/
void AudioPlayer::Pause()
{
if(!audio_data)return;
lock.Lock();
if(ps==PlayState::Play)
ps=PlayState::Pause;
2020-06-18 03:38:48 +08:00
lock.Unlock();
}
/**
*
*/
void AudioPlayer::Resume()
{
if(!audio_data)return;
lock.Lock();
if(ps==PlayState::Pause)
2020-06-18 03:38:48 +08:00
{
ps=PlayState::Play;
2020-06-18 03:38:48 +08:00
Thread::Start();
}
lock.Unlock();
}
bool AudioPlayer::UpdateBuffer()
{
int processed=0;
bool active=true;
alGetSourcei(source,AL_BUFFERS_PROCESSED,&processed); //取得处理结束的缓冲区数量
if(processed<=0)return(true);
const double cur_time=GetDoubleTime();
if(cur_time-start_time<fade_in_time) //淡入时间
{
audiosource.SetGain(((cur_time-start_time)/fade_in_time)*gain);
}
else
if(cur_time-start_time>total_time-fade_out_time) //淡出时间
2020-06-18 03:38:48 +08:00
{
audiosource.SetGain(((total_time-(cur_time-start_time))/fade_out_time)*gain);
2020-06-18 03:38:48 +08:00
}
if(auto_gain.open)
{
if(cur_time>=auto_gain.end.time)
{
auto_gain.open=false;
SetGain(auto_gain.end.gain);
2020-06-18 03:38:48 +08:00
if(auto_gain.end.gain<=0)
ps=PlayState::Exit;
2020-06-18 03:38:48 +08:00
}
else
{
SetGain(auto_gain.start.gain+auto_gain.gap*((cur_time-auto_gain.start.time)/auto_gain.time));
2020-06-18 03:38:48 +08:00
}
}
while(processed--)
{
ALuint buffer;
audio_buffer_count+=audio_buffer_size;
alSourceUnqueueBuffers(source,1,&buffer); //解除一个已处理完成的缓冲区
alLastError();
active=ReadData(buffer); //解码数据到这个缓冲区
if(active)
{
alSourceQueueBuffers(source,1,&buffer); //重新将这个缓冲区加入队列
alLastError();
}
else
return(false);
}
return(true);
}
void AudioPlayer::ClearBuffer()
{
int queued;
ALuint buffer;
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
while(queued--)
alSourceUnqueueBuffers(source, 1, &buffer);
}
bool AudioPlayer::Execute()
{
if(!audio_data)return(false);
while(true)
{
lock.Lock();
if(ps==PlayState::Play) //被要求播放
2020-06-18 03:38:48 +08:00
{
if(!UpdateBuffer())
{
if(loop) //被要求循环播放
{
if(GetSourceState()!=AL_STOPPED) //等它放完
2020-06-18 03:38:48 +08:00
Playback();
}
else
{
//退出
lock.Unlock();
ps=PlayState::None;
2020-06-18 03:38:48 +08:00
return(false);
}
}
else
{
if(GetSourceState()!=AL_PLAYING)
2020-06-18 03:38:48 +08:00
alSourcePlay(source);
}
}
else
if(ps==PlayState::Pause) //被要求暂停
2020-06-18 03:38:48 +08:00
{
alSourcePause(source);
lock.Unlock();
return(false);
}
else
if(ps==PlayState::Exit) //被要求暂停或退出
2020-06-18 03:38:48 +08:00
{
alSourceStop(source);
alSourcei(source,AL_BUFFER,0);
ClearBuffer();
lock.Unlock();
return(false);
}
lock.Unlock();
WaitTime(wait_time); //以让线程空出CPU时间片
}
}
double AudioPlayer::GetPlayTime()
{
if(!audio_data)return(0);
uint base=audio_buffer_count;
int off;
lock.Lock();
alGetSourcei(source,AL_BYTE_OFFSET,&off);
lock.Unlock();
return AudioDataTime(base+off,format,rate);
}
/**
*
* @param target_gain
* @param adjust_time
* @param cur_time
2020-06-18 03:38:48 +08:00
*/
void AudioPlayer::AutoGain(float target_gain,double adjust_time,const double cur_time)
2020-06-18 03:38:48 +08:00
{
if(!audio_data)return;
lock.Lock();
auto_gain.start.gain=GetGain();
auto_gain.start.time=cur_time;
2020-06-18 03:38:48 +08:00
auto_gain.end.gain=target_gain;
auto_gain.end.time=auto_gain.start.time+adjust_time;
auto_gain.time=adjust_time;
auto_gain.gap=target_gain-auto_gain.start.gain;
auto_gain.open=true;
lock.Unlock();
}
void AudioPlayer::SetFadeTime(double in,double out)
{
fade_in_time=in;
fade_out_time=out;
}
}//namespace hgl