1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
/*############################################################################*/
/*# #*/
/*# Ambisonic C++ Library #*/
/*# CAmbisonicEncoderDist - Ambisonic Encoder with distance #*/
/*# Copyright © 2007 Aristotel Digenis #*/
/*# #*/
/*# Filename: AmbisonicEncoderDist.cpp #*/
/*# Version: 0.1 #*/
/*# Date: 19/05/2007 #*/
/*# Author(s): Aristotel Digenis #*/
/*# Licence: MIT #*/
/*# #*/
/*############################################################################*/
#include "AmbisonicEncoderDist.h"
CAmbisonicEncoderDist::CAmbisonicEncoderDist()
{
m_nSampleRate = 0;
m_fDelay = 0.f;
m_nDelay = 0;
m_nDelayBufferLength = 0;
m_pfDelayBuffer = 0;
m_nIn = 0;
m_nOutA = 0;
m_nOutB = 0;
m_fRoomRadius = 5.f;
m_fInteriorGain = 0.f;
m_fExteriorGain = 0.f;
Configure(DEFAULT_ORDER, DEFAULT_HEIGHT, DEFAULT_SAMPLERATE);
}
CAmbisonicEncoderDist::~CAmbisonicEncoderDist()
{
if(m_pfDelayBuffer)
delete [] m_pfDelayBuffer;
}
bool CAmbisonicEncoderDist::Configure(unsigned nOrder, bool b3D, unsigned nSampleRate)
{
bool success = CAmbisonicEncoder::Configure(nOrder, b3D, 0);
if(!success)
return false;
m_nSampleRate = nSampleRate;
m_nDelayBufferLength = (unsigned)((float)knMaxDistance / knSpeedOfSound * m_nSampleRate + 0.5f);
if(m_pfDelayBuffer)
delete [] m_pfDelayBuffer;
m_pfDelayBuffer = new float[m_nDelayBufferLength];
Reset();
return true;
}
void CAmbisonicEncoderDist::Reset()
{
memset(m_pfDelayBuffer, 0, m_nDelayBufferLength * sizeof(float));
m_fDelay = m_polPosition.fDistance / knSpeedOfSound * m_nSampleRate + 0.5f;
m_nDelay = (int)m_fDelay;
m_fDelay -= m_nDelay;
m_nIn = 0;
m_nOutA = (m_nIn - m_nDelay + m_nDelayBufferLength) % m_nDelayBufferLength;
m_nOutB = (m_nOutA + 1) % m_nDelayBufferLength;
}
void CAmbisonicEncoderDist::Refresh()
{
CAmbisonicEncoder::Refresh();
m_fDelay = fabs(m_polPosition.fDistance) / knSpeedOfSound * m_nSampleRate; //TODO abs() sees float as int!
m_nDelay = (int)m_fDelay;
m_fDelay -= m_nDelay;
m_nOutA = (m_nIn - m_nDelay + m_nDelayBufferLength) % m_nDelayBufferLength;
m_nOutB = (m_nOutA + 1) % m_nDelayBufferLength;
//Source is outside speaker array
if(fabs(m_polPosition.fDistance) >= m_fRoomRadius)
{
m_fInteriorGain = (m_fRoomRadius / fabs(m_polPosition.fDistance)) / 2.f;
m_fExteriorGain = m_fInteriorGain;
}
else
{
m_fInteriorGain = (2.f - fabs(m_polPosition.fDistance) / m_fRoomRadius) / 2.f;
m_fExteriorGain = (fabs(m_polPosition.fDistance) / m_fRoomRadius) / 2.f;
}
}
void CAmbisonicEncoderDist::Process(float* pfSrc, unsigned nSamples, CBFormat* pfDst)
{
unsigned niChannel = 0;
unsigned niSample = 0;
float fSrcSample = 0;
for(niSample = 0; niSample < nSamples; niSample++)
{
//Store
m_pfDelayBuffer[m_nIn] = pfSrc[niSample];
//Read
fSrcSample = m_pfDelayBuffer[m_nOutA] * (1.f - m_fDelay)
+ m_pfDelayBuffer[m_nOutB] * m_fDelay;
pfDst->m_ppfChannels[kW][niSample] = fSrcSample * m_fInteriorGain * m_pfCoeff[kW];
fSrcSample *= m_fExteriorGain;
for(niChannel = 1; niChannel < m_nChannelCount; niChannel++)
{
pfDst->m_ppfChannels[niChannel][niSample] = fSrcSample * m_pfCoeff[niChannel];
}
m_nIn = (m_nIn + 1) % m_nDelayBufferLength;
m_nOutA = (m_nOutA + 1) % m_nDelayBufferLength;
m_nOutB = (m_nOutB + 1) % m_nDelayBufferLength;
}
}
void CAmbisonicEncoderDist::SetRoomRadius(float fRoomRadius)
{
m_fRoomRadius = fRoomRadius;
}
float CAmbisonicEncoderDist::GetRoomRadius()
{
return m_fRoomRadius;
}
|