373 lines
8.9 KiB
C++
373 lines
8.9 KiB
C++
#include"AudioSource.h"
|
||
|
||
AudioSource::AudioSource():
|
||
m_filter(64),
|
||
m_reberation(AUDIO_BUFFER_SIZE / 2, 44100, 0.5f),
|
||
m_hrtf_filter_L(128),
|
||
m_hrtf_filter_R(128)
|
||
{
|
||
HRTFInitialize();
|
||
|
||
return;
|
||
//---------------------------------------------------------待删
|
||
std::vector<float> lowPassKernel(64, 0.0f);
|
||
float cutoffFrequency = 1000.0f; // 截止频率为1000 Hz
|
||
float nyquistFrequency = 0.5f * 44100.0f; // Nyquist频率
|
||
int numTaps = 64; // 滤波器长度
|
||
for (int i = 0; i < numTaps; ++i) {
|
||
float frequency = i * nyquistFrequency / numTaps;
|
||
if (frequency <= cutoffFrequency) {
|
||
lowPassKernel[i] = 1.0f; // 低通滤波器
|
||
}
|
||
}
|
||
m_filter.SetTimeDomainKernel(lowPassKernel);
|
||
}
|
||
|
||
AudioSource::~AudioSource()
|
||
{
|
||
m_historyEnergys.clear();
|
||
}
|
||
|
||
void AudioSource::HRTFInitialize()
|
||
{
|
||
/*hrtf-filter*/
|
||
m_hrtf.SetDirection(0, 0);
|
||
std::vector<float> hrtfData;
|
||
m_hrtf.GetLeftEarTimeHRTF(hrtfData);
|
||
for (int i = 0; i < 128; i++)
|
||
{
|
||
hrtfData[i] /= (float)32767;
|
||
}
|
||
m_hrtf_filter_L.SetTimeDomainKernel(hrtfData);
|
||
hrtfData.clear();
|
||
m_hrtf.GetRightEarTimeHRTF(hrtfData);
|
||
for (int i = 0; i < 128; i++)
|
||
{
|
||
hrtfData[i] /= (float)32767;
|
||
}
|
||
m_hrtf_filter_R.SetTimeDomainKernel(hrtfData);
|
||
|
||
/*fade-window*/
|
||
m_fade_window.resize(m_bufferSize / 2.);
|
||
double phase_step = PI / 2. / (m_bufferSize / 2. - 1);
|
||
for (int i = 0; i < m_bufferSize / 2.; i++)
|
||
{
|
||
m_fade_window[i] = sin(i * phase_step);
|
||
m_fade_window[i] *= m_fade_window[i];
|
||
}
|
||
}
|
||
|
||
void AudioSource::Play()
|
||
{
|
||
if (!m_isLoaded) { return; }
|
||
m_isActive = true;
|
||
m_lastingTime = 0;
|
||
}
|
||
|
||
void AudioSource::Load(AudioClip* p_clip)
|
||
{
|
||
m_isLoaded = false;
|
||
//TODO:检查音频文件的后缀名,用相应的filereader打开
|
||
m_wavReader = new WavFileReader();
|
||
if (!m_wavReader->OpenFile(std::string(p_clip->GetName()))) { return; }
|
||
m_isLoaded = true;
|
||
m_audioClip = p_clip;
|
||
m_energyRate = m_wavReader->GetSampleRate() / (float)1024;
|
||
}
|
||
|
||
void AudioSource::Update(double p_deltaTime)
|
||
{
|
||
if (!m_isActive || !m_audioClip) { return; }
|
||
m_lastingTime += p_deltaTime;
|
||
|
||
|
||
/*energy-detect*/
|
||
if (m_isEnergyDetecting)
|
||
{
|
||
int index = m_lastingTime * m_energyRate;
|
||
/*this-energy*/
|
||
m_thisEnergy = 0;
|
||
for (int i = 0; i < m_wavReader->GetChannels() * 1024; i++)
|
||
{
|
||
m_thisEnergy += pow(m_wavReader->GetSampleValue(m_wavReader->GetChannels() * 1024 * index + i), 2);
|
||
}
|
||
/*averge-energy*/
|
||
for (int j = m_avergeOldIndex + 1; j < index; j++)
|
||
{
|
||
long long historyEnergy = 0;
|
||
for (int i = 0; i < m_wavReader->GetChannels() * 1024; i++)
|
||
{
|
||
historyEnergy += pow(m_wavReader->GetSampleValue(m_wavReader->GetChannels() * 1024 * j + i), 2);
|
||
}
|
||
/*calaulate-averge*/
|
||
if (m_avergeOldIndex < (int)m_energyRate - 1)
|
||
{
|
||
m_avergeEnergy *= m_avergeOldIndex;
|
||
m_avergeEnergy += historyEnergy;
|
||
m_avergeOldIndex += 1;
|
||
m_avergeEnergy /= m_avergeOldIndex;
|
||
m_historyEnergys.push_front(historyEnergy);
|
||
}
|
||
else
|
||
{
|
||
m_avergeEnergy *= (int)m_energyRate;
|
||
m_avergeEnergy += historyEnergy;
|
||
m_historyEnergys.push_front(historyEnergy);
|
||
m_avergeEnergy -= m_historyEnergys.back();
|
||
m_avergeEnergy /= (int)m_energyRate;
|
||
m_avergeOldIndex += 1;
|
||
m_historyEnergys.pop_back();
|
||
}
|
||
}
|
||
m_thisEnergyScale = m_avergeEnergy == 0 ? 0 : m_thisEnergy / (float)m_avergeEnergy;
|
||
m_thisEnergyScale = m_thisEnergyScale < m_maxEnergyScale ? m_thisEnergyScale : m_maxEnergyScale;
|
||
}
|
||
}
|
||
|
||
float AudioSource::GetEnergy()
|
||
{
|
||
return m_thisEnergyScale;
|
||
}
|
||
|
||
void AudioSource::StartEnergyDetect()
|
||
{
|
||
m_isEnergyDetecting = true;
|
||
}
|
||
|
||
void AudioSource::CloseEnergyDetect()
|
||
{
|
||
m_isEnergyDetecting = false;
|
||
}
|
||
|
||
|
||
short* AudioSource::GetBufferData()
|
||
{
|
||
return m_buffer;
|
||
}
|
||
|
||
void AudioSource::PrepareBufferData()
|
||
{
|
||
/*dry-audio*/
|
||
float sample = 0;
|
||
std::vector<float> samples;
|
||
for (int i = 0; i < m_bufferSize; i++)
|
||
{
|
||
m_sampleIndex++;
|
||
std::vector<float> data;
|
||
if (m_sampleIndex >= m_wavReader->GetSampleNum())
|
||
{
|
||
sample += 0;
|
||
m_isActive = false;
|
||
continue;
|
||
}
|
||
sample += m_wavReader->GetSampleValue(m_sampleIndex);
|
||
|
||
if (i % 2 == 1)
|
||
{
|
||
samples.push_back(sample / 2.);
|
||
sample = 0;
|
||
}
|
||
}
|
||
|
||
|
||
//####/*hrtf*/####
|
||
/*caculate hrtf result*/
|
||
std::vector<float> hrtfLeft(m_bufferSize / 2, 0);
|
||
std::vector<float> hrtfRight(m_bufferSize / 2, 0);
|
||
|
||
for (int i = 0; i < AUDIO_BUFFER_SIZE / 2 / 128; i++)
|
||
{
|
||
std::vector<float> subSamples(128);
|
||
std::vector<float> subHrtfLeft(128);
|
||
std::vector<float> subHrtfRight(128);
|
||
std::copy(samples.begin() + i * 128, samples.begin() + (i + 1) * 128, subSamples.begin());
|
||
|
||
m_hrtf_filter_L.AddSignalBlock(subSamples);
|
||
m_hrtf_filter_L.GetResult(&subHrtfLeft);
|
||
std::copy(subHrtfLeft.begin(), subHrtfLeft.end(), hrtfLeft.begin() + 128 * i);
|
||
|
||
m_hrtf_filter_R.AddSignalBlock(subSamples);
|
||
m_hrtf_filter_R.GetResult(&subHrtfRight);
|
||
std::copy(subHrtfRight.begin(), subHrtfRight.end(), hrtfRight.begin() + 128 * i);
|
||
}
|
||
|
||
/*direction-changed*/
|
||
if (m_hrtf.SetDirection(m_elevation, m_azimuth))
|
||
{
|
||
/*change-kernel*/
|
||
std::vector<float> hrtfData;
|
||
m_hrtf.GetLeftEarTimeHRTF(hrtfData);
|
||
for (int i = 0; i < 128; i++)
|
||
{
|
||
hrtfData[i] /= (float)32767;
|
||
}
|
||
m_hrtf_filter_L.SetTimeDomainKernel(hrtfData);
|
||
hrtfData.clear();
|
||
m_hrtf.GetRightEarTimeHRTF(hrtfData);
|
||
for (int i = 0; i < 128; i++)
|
||
{
|
||
hrtfData[i] /= (float)32767;
|
||
}
|
||
m_hrtf_filter_R.SetTimeDomainKernel(hrtfData);
|
||
|
||
/*caculate new hrtf result*/
|
||
std::vector<float> newHrtfLeft(m_bufferSize / 2, 0);
|
||
std::vector<float> newHrtfRight(m_bufferSize / 2, 0);
|
||
|
||
for (int i = 0; i < AUDIO_BUFFER_SIZE / 2 / 128; i++)
|
||
{
|
||
std::vector<float> subSamples(128);
|
||
std::vector<float> subHrtfLeft(128);
|
||
std::vector<float> subHrtfRight(128);
|
||
std::copy(samples.begin() + i * 128, samples.begin() + (i + 1) * 128, subSamples.begin());
|
||
|
||
m_hrtf_filter_L.AddSignalBlock(subSamples);
|
||
m_hrtf_filter_L.GetResult(&subHrtfLeft);
|
||
std::copy(subHrtfLeft.begin(), subHrtfLeft.end(), newHrtfLeft.begin() + 128 * i);
|
||
|
||
m_hrtf_filter_R.AddSignalBlock(subSamples);
|
||
m_hrtf_filter_R.GetResult(&subHrtfRight);
|
||
std::copy(subHrtfRight.begin(), subHrtfRight.end(), newHrtfRight.begin() + 128 * i);
|
||
}
|
||
|
||
/*apply fade window*/
|
||
ApplyFadeWindow(hrtfLeft, newHrtfLeft, &hrtfLeft);
|
||
ApplyFadeWindow(hrtfRight, newHrtfRight, &hrtfRight);
|
||
}
|
||
|
||
|
||
for (int i = 0; i < m_bufferSize; i++)
|
||
{
|
||
if (i % 2 == 0)
|
||
{
|
||
m_buffer[i] = hrtfLeft[i / 2];
|
||
}
|
||
else
|
||
{
|
||
m_buffer[i] = hrtfRight[i / 2];
|
||
}
|
||
}
|
||
}
|
||
|
||
void AudioSource::ApplyFadeWindow(const std::vector<float>& p_block_last, const std::vector<float>& p_block_next, std::vector<float>* p_fade_result)
|
||
{
|
||
for (int i = 0; i < m_bufferSize / 2.; i++)
|
||
{
|
||
(*p_fade_result)[i] = p_block_last[i] * m_fade_window[m_bufferSize / 2. - 1 - i] + p_block_next[i] * m_fade_window[i];
|
||
}
|
||
}
|
||
|
||
void AudioSource::SetDirection(int p_elevation, int p_azimuth)
|
||
{
|
||
if (p_elevation > 90) { p_elevation = 90; }
|
||
if (p_elevation < -90) { p_elevation = -90; }
|
||
m_azimuth = p_azimuth;
|
||
m_elevation = p_elevation;
|
||
}
|
||
|
||
|
||
/*
|
||
float sample = 0;
|
||
std::vector<float> samples;
|
||
for (int i = 0; i < m_bufferSize; i++)
|
||
{
|
||
m_sampleIndex++;
|
||
std::vector<float> data;
|
||
if (m_sampleIndex >= m_wavReader->GetSampleNum())
|
||
{
|
||
sample += 0;
|
||
m_isActive = false;
|
||
continue;
|
||
}
|
||
sample += m_wavReader->GetSampleValue(m_sampleIndex);
|
||
|
||
if (i % 2 == 1)
|
||
{
|
||
samples.push_back(sample / 2.);
|
||
sample = 0;
|
||
}
|
||
}
|
||
|
||
std::vector<float> reberationLeft(m_bufferSize / 2, 0);
|
||
std::vector<float> reberationRight(m_bufferSize / 2, 0);
|
||
m_reberation.AddReberation(samples, &reberationLeft, &reberationRight);
|
||
|
||
for (int i = 0; i < m_bufferSize; i++)
|
||
{
|
||
if (i % 2 == 0)
|
||
{
|
||
m_buffer[i] = reberationLeft[i / 2];
|
||
}
|
||
else
|
||
{
|
||
m_buffer[i] = reberationRight[i / 2];
|
||
}
|
||
}
|
||
*/
|
||
/*
|
||
|
||
float sample = 0;
|
||
std::vector<float> samples;
|
||
for (int i = 0; i < m_bufferSize; i++)
|
||
{
|
||
m_sampleIndex++;
|
||
std::vector<float> data;
|
||
if (m_sampleIndex >= m_wavReader->GetSampleNum())
|
||
{
|
||
sample += 0;
|
||
m_isActive = false;
|
||
continue;
|
||
}
|
||
sample += m_wavReader->GetSampleValue(m_sampleIndex);
|
||
|
||
if (i % 2 == 1)
|
||
{
|
||
samples.push_back(sample / 2.);
|
||
sample = 0;
|
||
}
|
||
}
|
||
|
||
std::vector<float> hrtfLeft(m_bufferSize / 2, 0);
|
||
std::vector<float> hrtfRight(m_bufferSize / 2, 0);
|
||
|
||
for (int i = 0; i < AUDIO_BUFFER_SIZE / 2 / 128; i++)
|
||
{
|
||
std::vector<float> subSamples(128);
|
||
std::vector<float> subHrtfLeft(128);
|
||
std::vector<float> subHrtfRight(128);
|
||
std::copy(samples.begin() + i * 128, samples.begin() + (i + 1) * 128, subSamples.begin());
|
||
|
||
m_hrtf_filter_L.AddSignalBlock(subSamples);
|
||
m_hrtf_filter_L.GetResult(&subHrtfLeft);
|
||
std::copy(subHrtfLeft.begin(), subHrtfLeft.end(), hrtfLeft.begin() + 128 * i);
|
||
|
||
m_hrtf_filter_R.AddSignalBlock(subSamples);
|
||
m_hrtf_filter_R.GetResult(&subHrtfRight);
|
||
std::copy(subHrtfRight.begin(), subHrtfRight.end(), hrtfRight.begin() + 128 * i);
|
||
}
|
||
|
||
for (int i = 0; i < m_bufferSize; i++)
|
||
{
|
||
if (i % 2 == 0)
|
||
{
|
||
m_buffer[i] = hrtfLeft[i / 2];
|
||
}
|
||
else
|
||
{
|
||
m_buffer[i] = hrtfRight[i / 2];
|
||
}
|
||
}
|
||
*/
|
||
/*
|
||
for (int i = 0; i < m_bufferSize; i++)
|
||
{
|
||
if (i % 2 == 0)
|
||
{
|
||
m_buffer[i] = samples[i / 2];
|
||
}
|
||
else
|
||
{
|
||
m_buffer[i] = samples[i / 2];
|
||
}
|
||
}
|
||
*/ |