Files
XCEngine/MVS/Music fluctuations/source/audio/AudioSource.cpp

373 lines
8.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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];
}
}
*/