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;
|
|||
|
|
//---------------------------------------------------------<2D><>ɾ
|
|||
|
|
std::vector<float> lowPassKernel(64, 0.0f);
|
|||
|
|
float cutoffFrequency = 1000.0f; // <20><>ֹƵ<D6B9><C6B5>Ϊ1000 Hz
|
|||
|
|
float nyquistFrequency = 0.5f * 44100.0f; // NyquistƵ<74><C6B5>
|
|||
|
|
int numTaps = 64; // <20>˲<EFBFBD><CBB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
for (int i = 0; i < numTaps; ++i) {
|
|||
|
|
float frequency = i * nyquistFrequency / numTaps;
|
|||
|
|
if (frequency <= cutoffFrequency) {
|
|||
|
|
lowPassKernel[i] = 1.0f; // <20><>ͨ<EFBFBD>˲<EFBFBD><CBB2><EFBFBD>
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
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:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ļ<EFBFBD><C4BC>ĺ<EFBFBD><EFBFBD><D7BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>filereader<65><72><EFBFBD><EFBFBD>
|
|||
|
|
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];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
*/
|