Added: Support for independent filter sets per channel. The new command "Channel" allows to specify the channel(s) to which the following "Filter" and "Preamp" commands should apply.
This commit is contained in:
1 parent
cd53c16c17
commit
fb5020e72f
4 files changed
+295
-67
No files matched your search
@@ -34,6 +34,7 @@ int main(int argc, char** argv)
|
||||
{
|
||||
unsigned sampleRate;
|
||||
unsigned channelCount;
|
||||
unsigned channelMask;
|
||||
unsigned frameCount;
|
||||
float* buf;
|
||||
|
||||
@@ -50,6 +51,7 @@ int main(int argc, char** argv)
|
||||
|
||||
sampleRate = info.samplerate;
|
||||
channelCount = info.channels;
|
||||
channelMask = 0;
|
||||
frameCount = (unsigned)info.frames;
|
||||
|
||||
buf = new float[frameCount * channelCount];
|
||||
@@ -65,11 +67,12 @@ int main(int argc, char** argv)
|
||||
{
|
||||
sampleRate = 44100;
|
||||
channelCount = 1;
|
||||
frameCount = 8820000;
|
||||
channelMask = 0;
|
||||
float sweepFrom = 0.1f;
|
||||
float sweepTo = 20000;
|
||||
float sweepDiff = sweepTo - sweepFrom;
|
||||
float length = 200;
|
||||
frameCount = (unsigned)(length * sampleRate);
|
||||
|
||||
printf("No input file given, so generating linear sine sweep from %g to %g Hz over %g seconds\n", sweepFrom, sweepTo, length);
|
||||
|
||||
@@ -88,7 +91,7 @@ int main(int argc, char** argv)
|
||||
|
||||
ParametricEQ peq;
|
||||
peq.setDeviceInfo(L"Benchmark", L"File output", L"");
|
||||
peq.initialize((float)sampleRate, channelCount);
|
||||
peq.initialize((float)sampleRate, channelCount, channelMask);
|
||||
|
||||
PrecisionTimer timer;
|
||||
timer.start();
|
||||
|
||||
+30
-3
@@ -195,6 +195,18 @@ HRESULT EqualizerAPO::IsInputFormatSupported(IAudioMediaType* pOutputFormat,
|
||||
TraceF(L"RequestedInputFormat = { %08X, %u, %u, %u, %f, %08X }",
|
||||
inFormat.guidFormatType.Data1, inFormat.dwSamplesPerFrame, inFormat.dwBytesPerSampleContainer,
|
||||
inFormat.dwValidBitsPerSample, inFormat.fFramesPerSecond, inFormat.dwChannelMask);
|
||||
|
||||
UNCOMPRESSEDAUDIOFORMAT outFormat;
|
||||
hr = pOutputFormat->GetUncompressedAudioFormat(&outFormat);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
LogF(L"Error in second GetUncompressedAudioFormat");
|
||||
return hr;
|
||||
}
|
||||
|
||||
TraceF(L"Output format = { %08X, %u, %u, %u, %f, %08X }",
|
||||
outFormat.guidFormatType.Data1, outFormat.dwSamplesPerFrame, outFormat.dwBytesPerSampleContainer,
|
||||
outFormat.dwValidBitsPerSample, outFormat.fFramesPerSecond, outFormat.dwChannelMask);
|
||||
|
||||
if(childAPO)
|
||||
{
|
||||
@@ -270,15 +282,30 @@ HRESULT EqualizerAPO::LockForProcess(UINT32 u32NumInputConnections,
|
||||
return hr;
|
||||
}
|
||||
|
||||
UNCOMPRESSEDAUDIOFORMAT uncompAudioFormat;
|
||||
hr = ppOutputConnections[0]->pFormat->GetUncompressedAudioFormat(&uncompAudioFormat);
|
||||
UNCOMPRESSEDAUDIOFORMAT inFormat;
|
||||
hr = ppInputConnections[0]->pFormat->GetUncompressedAudioFormat(&inFormat);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
LogF(L"Error in GetUncompressedAudioFormat in LockForProcess");
|
||||
return hr;
|
||||
}
|
||||
|
||||
peq.initialize(uncompAudioFormat.fFramesPerSecond, uncompAudioFormat.dwSamplesPerFrame);
|
||||
TraceF(L"Input format in LockForProcess = { %08X, %u, %u, %u, %f, %08X }",
|
||||
inFormat.guidFormatType.Data1, inFormat.dwSamplesPerFrame, inFormat.dwBytesPerSampleContainer,
|
||||
inFormat.dwValidBitsPerSample, inFormat.fFramesPerSecond, inFormat.dwChannelMask);
|
||||
|
||||
UNCOMPRESSEDAUDIOFORMAT outFormat;
|
||||
hr = ppOutputConnections[0]->pFormat->GetUncompressedAudioFormat(&outFormat);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
LogF(L"Error in second GetUncompressedAudioFormat in LockForProcess");
|
||||
return hr;
|
||||
}
|
||||
|
||||
TraceF(L"Output format in LockForProcess = { %08X, %u, %u, %u, %f, %08X }",
|
||||
outFormat.guidFormatType.Data1, outFormat.dwSamplesPerFrame, outFormat.dwBytesPerSampleContainer,
|
||||
outFormat.dwValidBitsPerSample, outFormat.fFramesPerSecond, outFormat.dwChannelMask);
|
||||
peq.initialize(outFormat.fFramesPerSecond, outFormat.dwSamplesPerFrame, outFormat.dwChannelMask);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
+203
-52
@@ -26,6 +26,8 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <Ks.h>
|
||||
#include <KsMedia.h>
|
||||
|
||||
#include "StringHelper.h"
|
||||
#include "RegistryHelper.h"
|
||||
@@ -52,20 +54,30 @@ BiQuad::BiQuad(float dbGain, float freq, float srate, float bandwidthOrQ, bool i
|
||||
a[1] = (1 - (alpha * A)) / temp;
|
||||
a[2] = - (-2 * cs) / temp;
|
||||
a[3] = - (1 - (alpha /A)) / temp;
|
||||
|
||||
x1 = 0;
|
||||
x2 = 0;
|
||||
y1 = 0;
|
||||
y2 = 0;
|
||||
}
|
||||
|
||||
ChannelData::ChannelData()
|
||||
{
|
||||
preamp = 1.0f;
|
||||
filterCount = 0;
|
||||
}
|
||||
|
||||
ParametricEQ::ParametricEQ()
|
||||
{
|
||||
filterCount = 0;
|
||||
channelCount = 0;
|
||||
preamp = 1.0f;
|
||||
memset(sampleData, 0, 1000 * sizeof(float));
|
||||
channelData = NULL;
|
||||
lastInputWasSilent = false;
|
||||
threadHandle = NULL;
|
||||
}
|
||||
|
||||
ParametricEQ::~ParametricEQ()
|
||||
{
|
||||
// Make sure notification thread is terminated before cleaning up, otherwise deleted memory might be accessed in loadConfig
|
||||
if(threadHandle != NULL)
|
||||
{
|
||||
SetEvent(shutdownEvent);
|
||||
@@ -77,6 +89,12 @@ ParametricEQ::~ParametricEQ()
|
||||
CloseHandle(threadHandle);
|
||||
threadHandle = NULL;
|
||||
}
|
||||
|
||||
if(channelData != NULL)
|
||||
{
|
||||
delete[] channelData;
|
||||
channelData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ParametricEQ::setDeviceInfo(const wstring& deviceName, const wstring& connectionName, const wstring& deviceGuid)
|
||||
@@ -86,13 +104,34 @@ void ParametricEQ::setDeviceInfo(const wstring& deviceName, const wstring& conne
|
||||
this->deviceGuid = deviceGuid;
|
||||
}
|
||||
|
||||
void ParametricEQ::initialize(float sampleRate, unsigned channelCount)
|
||||
void ParametricEQ::initialize(float sampleRate, unsigned channelCount, unsigned channelMask)
|
||||
{
|
||||
this->sampleRate = sampleRate;
|
||||
this->channelCount = channelCount;
|
||||
memset(sampleData, 0, 1000 * sizeof(float));
|
||||
filterCount = 0;
|
||||
preamp = 1.0f;
|
||||
channelData = new ChannelData[channelCount];
|
||||
|
||||
if(channelMask == 0)
|
||||
{
|
||||
switch(channelCount)
|
||||
{
|
||||
case 1:
|
||||
channelMask = KSAUDIO_SPEAKER_MONO;
|
||||
break;
|
||||
case 2:
|
||||
channelMask = KSAUDIO_SPEAKER_STEREO;
|
||||
break;
|
||||
case 4:
|
||||
channelMask = KSAUDIO_SPEAKER_QUAD;
|
||||
break;
|
||||
case 6:
|
||||
channelMask = KSAUDIO_SPEAKER_5POINT1_SURROUND;
|
||||
break;
|
||||
case 8:
|
||||
channelMask = KSAUDIO_SPEAKER_7POINT1_SURROUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->channelMask = channelMask;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -123,17 +162,27 @@ void ParametricEQ::initialize(float sampleRate, unsigned channelCount)
|
||||
|
||||
void ParametricEQ::loadConfig()
|
||||
{
|
||||
unsigned loadFilterCount = 0;
|
||||
float loadPreamp = 1.0f;
|
||||
for(unsigned c=0; c<channelCount; c++)
|
||||
{
|
||||
channelData[c].loadPreamp = 1.0f;
|
||||
channelData[c].loadFilterCount = 0;
|
||||
}
|
||||
|
||||
loadConfig(configPath + L"\\config.txt", loadFilterCount, loadPreamp);
|
||||
vector<bool> selectedChannels(channelCount, true);
|
||||
loadConfig(configPath + L"\\config.txt", selectedChannels);
|
||||
|
||||
unsigned loadFilterCount = 0;
|
||||
for(unsigned c=0; c<channelCount; c++)
|
||||
{
|
||||
channelData[c].preamp = channelData[c].loadPreamp;
|
||||
channelData[c].filterCount = channelData[c].loadFilterCount;
|
||||
loadFilterCount += channelData[c].loadFilterCount;
|
||||
}
|
||||
|
||||
TraceF(L"%d filters loaded", loadFilterCount);
|
||||
preamp = loadPreamp;
|
||||
filterCount = loadFilterCount;
|
||||
}
|
||||
|
||||
void ParametricEQ::loadConfig(wstring path, unsigned& loadFilterCount, float& loadPreamp)
|
||||
void ParametricEQ::loadConfig(const wstring& path, vector<bool> selectedChannels)
|
||||
{
|
||||
TraceF(L"Loading configuration from %s", path.c_str());
|
||||
|
||||
@@ -188,7 +237,7 @@ void ParametricEQ::loadConfig(wstring path, unsigned& loadFilterCount, float& lo
|
||||
}
|
||||
else
|
||||
{
|
||||
currentWord += value[i];
|
||||
currentWord += c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,31 +271,120 @@ void ParametricEQ::loadConfig(wstring path, unsigned& loadFilterCount, float& lo
|
||||
if(!deviceMatches)
|
||||
continue;
|
||||
|
||||
if(key.find(L"Filter") == 0)
|
||||
if(key == L"Channel")
|
||||
{
|
||||
selectedChannels = vector<bool>(channelCount, false);
|
||||
|
||||
value = value + L" ";
|
||||
|
||||
wstring currentWord;
|
||||
for(unsigned i=0; i<value.length(); i++)
|
||||
{
|
||||
wchar_t c = towlower(value[i]);
|
||||
|
||||
if(c == L' ')
|
||||
{
|
||||
if(currentWord.length() > 0)
|
||||
{
|
||||
int channelNr = -1;
|
||||
|
||||
if(currentWord == L"all")
|
||||
{
|
||||
selectedChannels = vector<bool>(channelCount, true);
|
||||
}
|
||||
else if(iswdigit(currentWord[0]))
|
||||
{
|
||||
channelNr = wcstol(currentWord.c_str(), NULL, 10) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int channelPos = -1;
|
||||
if(currentWord == L"l")
|
||||
channelPos = SPEAKER_FRONT_LEFT;
|
||||
else if(currentWord == L"r")
|
||||
channelPos = SPEAKER_FRONT_RIGHT;
|
||||
else if(currentWord == L"c")
|
||||
channelPos = SPEAKER_FRONT_CENTER;
|
||||
else if(currentWord == L"sub")
|
||||
channelPos = SPEAKER_LOW_FREQUENCY;
|
||||
else if(currentWord == L"rl")
|
||||
channelPos = SPEAKER_BACK_LEFT;
|
||||
else if(currentWord == L"rr")
|
||||
channelPos = SPEAKER_BACK_RIGHT;
|
||||
else if(currentWord == L"rc")
|
||||
channelPos = SPEAKER_BACK_CENTER;
|
||||
else if(currentWord == L"sl")
|
||||
channelPos = SPEAKER_SIDE_LEFT;
|
||||
else if(currentWord == L"sr")
|
||||
channelPos = SPEAKER_SIDE_RIGHT;
|
||||
else
|
||||
LogF(L"Invalid channel position %s", currentWord.c_str());
|
||||
|
||||
if(channelPos != -1)
|
||||
channelNr = getChannelNumber(channelPos);
|
||||
}
|
||||
|
||||
if(channelNr != -1 && channelNr < (int)channelCount)
|
||||
{
|
||||
selectedChannels[channelNr] = true;
|
||||
}
|
||||
|
||||
currentWord.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentWord += c;
|
||||
}
|
||||
}
|
||||
|
||||
wstringstream channelStream;
|
||||
for(unsigned c=0; c<channelCount; c++)
|
||||
{
|
||||
if(selectedChannels[c])
|
||||
{
|
||||
if(channelStream.tellp() > 0)
|
||||
channelStream << L", ";
|
||||
channelStream << c+1;
|
||||
}
|
||||
}
|
||||
|
||||
TraceF(L"Selecting channel(s) %s", channelStream.str().c_str());
|
||||
}
|
||||
else if(key.find(L"Filter") == 0)
|
||||
{
|
||||
//Conversion to period as decimal mark, if needed
|
||||
value = StringHelper::replaceCharacters(value, L",", L'.');
|
||||
|
||||
if(loadFilterCount < (sizeof(filters)/sizeof(BiQuad)))
|
||||
wchar_t freqString[10];
|
||||
float freq, gain, bandwidth;
|
||||
|
||||
int matched = swscanf_s(value.c_str(), L" ON PEQ Fc %9s Hz Gain %f dB BW Oct %f", &freqString, 10, &gain, &bandwidth);
|
||||
if(matched == 3 && (freq = getFreq(freqString)) != -1.0f)
|
||||
{
|
||||
wchar_t freqString[10];
|
||||
float freq, gain, bandwidth;
|
||||
|
||||
int matched = swscanf_s(value.c_str(), L" ON PEQ Fc %9s Hz Gain %f dB BW Oct %f", &freqString, 10, &gain, &bandwidth);
|
||||
for(unsigned c=0; c<channelCount; c++)
|
||||
{
|
||||
if(selectedChannels[c] && channelData[c].loadFilterCount < (sizeof(channelData[c].filters)/sizeof(BiQuad)))
|
||||
{
|
||||
channelData[c].filters[channelData[c].loadFilterCount++] = BiQuad(gain, freq, sampleRate, bandwidth, false);
|
||||
}
|
||||
}
|
||||
TraceF(L"Adding filter with center frequency %g Hz, gain %g dB and bandwidth %g octaves", freq, gain, bandwidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
float q;
|
||||
matched = swscanf_s(value.c_str(), L" ON PK Fc %9s Hz Gain %f dB Q %f", &freqString, 10, &gain, &q);
|
||||
if(matched == 3 && (freq = getFreq(freqString)) != -1.0f)
|
||||
{
|
||||
filters[loadFilterCount++] = BiQuad(gain, freq, sampleRate, bandwidth, false);
|
||||
TraceF(L"Adding filter with center frequency %g Hz, gain %g dB and bandwidth %g octaves", freq, gain, bandwidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
float q;
|
||||
matched = swscanf_s(value.c_str(), L" ON PK Fc %9s Hz Gain %f dB Q %f", &freqString, 10, &gain, &q);
|
||||
if(matched == 3 && (freq = getFreq(freqString)) != -1.0f)
|
||||
for(unsigned c=0; c<channelCount; c++)
|
||||
{
|
||||
filters[loadFilterCount++] = BiQuad(gain, freq, sampleRate, q, true);
|
||||
TraceF(L"Adding filter with center frequency %g Hz, gain %g dB and Q %g", freq, gain, q);
|
||||
if(selectedChannels[c] && channelData[c].loadFilterCount < (sizeof(channelData[c].filters)/sizeof(BiQuad)))
|
||||
{
|
||||
channelData[c].filters[channelData[c].loadFilterCount++] = BiQuad(gain, freq, sampleRate, q, true);
|
||||
}
|
||||
}
|
||||
TraceF(L"Adding filter with center frequency %g Hz, gain %g dB and Q %g", freq, gain, q);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -259,8 +397,15 @@ void ParametricEQ::loadConfig(wstring path, unsigned& loadFilterCount, float& lo
|
||||
int matched = swscanf_s(value.c_str(), L" %f dB", &preamp_dB);
|
||||
if(matched == 1)
|
||||
{
|
||||
loadPreamp = pow(10.0f, preamp_dB / 20.0f);
|
||||
TraceF(L"Setting preamp to %g dB", preamp_dB);
|
||||
for(unsigned c=0; c<channelCount; c++)
|
||||
{
|
||||
if(selectedChannels[c])
|
||||
{
|
||||
channelData[c].loadPreamp *= pow(10.0f, preamp_dB / 20.0f);
|
||||
}
|
||||
}
|
||||
|
||||
TraceF(L"Adjusting preamp by %g dB", preamp_dB);
|
||||
}
|
||||
}
|
||||
else if(key == L"Include")
|
||||
@@ -284,14 +429,12 @@ void ParametricEQ::loadConfig(wstring path, unsigned& loadFilterCount, float& lo
|
||||
else
|
||||
includePath = value;
|
||||
|
||||
loadConfig(includePath, loadFilterCount, loadPreamp);
|
||||
loadConfig(includePath, selectedChannels);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define IS_DENORMAL(f) (((*(unsigned int *)&(f))&0x7f800000) == 0)
|
||||
|
||||
void ParametricEQ::process(float *output, float *input, unsigned frameCount)
|
||||
{
|
||||
bool inputSilent = true;
|
||||
@@ -322,32 +465,25 @@ void ParametricEQ::process(float *output, float *input, unsigned frameCount)
|
||||
lastInputWasSilent = false;
|
||||
|
||||
//Avoid denormals
|
||||
for(unsigned i = 0; i < (filterCount+1)*channelCount*2; i++)
|
||||
if(IS_DENORMAL(sampleData[i]))
|
||||
sampleData[i] = 0;
|
||||
for (unsigned c=0; c<channelCount; c++)
|
||||
{
|
||||
for(unsigned f=0; f<channelData[c].filterCount; f++)
|
||||
{
|
||||
channelData[c].filters[f].removeDenormals();
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < frameCount * channelCount; i+=channelCount)
|
||||
for (unsigned c=0; c<channelCount; c++)
|
||||
{
|
||||
float sample = input[i+c];
|
||||
|
||||
for(unsigned f=0; f<filterCount; f++)
|
||||
for(unsigned f=0; f<channelData[c].filterCount; f++)
|
||||
{
|
||||
unsigned dataIndex = (c*(filterCount+1) + f)*2;
|
||||
float result = filters[f].a0 * sample + filters[f].a[0] * sampleData[dataIndex] + filters[f].a[1] * sampleData[dataIndex+1] +
|
||||
filters[f].a[2] * sampleData[dataIndex+2] + filters[f].a[3] * sampleData[dataIndex+3];
|
||||
|
||||
sampleData[dataIndex+1] = sampleData[dataIndex];
|
||||
sampleData[dataIndex] = sample;
|
||||
|
||||
//Input for next stage
|
||||
sample = result;
|
||||
sample = channelData[c].filters[f].process(sample);
|
||||
}
|
||||
unsigned lastIndex = (c*(filterCount+1) + filterCount)*2;
|
||||
sampleData[lastIndex + 1] = sampleData[lastIndex];
|
||||
sampleData[lastIndex] = sample;
|
||||
|
||||
output[i+c] = sample * preamp;
|
||||
output[i+c] = sample * channelData[c].preamp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,6 +508,21 @@ float ParametricEQ::getFreq(const wstring& freqString)
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
unsigned ParametricEQ::getChannelNumber(unsigned position)
|
||||
{
|
||||
if((channelMask & position) == 0)
|
||||
return -1;
|
||||
|
||||
int channelNr = 0;
|
||||
for(unsigned i=1; i<position; i<<=1)
|
||||
{
|
||||
if(channelMask & i)
|
||||
channelNr++;
|
||||
}
|
||||
|
||||
return channelNr;
|
||||
}
|
||||
|
||||
unsigned long __stdcall ParametricEQ::notificationThread(void* parameter)
|
||||
{
|
||||
ParametricEQ* peq = (ParametricEQ*)parameter;
|
||||
|
||||
+57
-10
@@ -20,14 +20,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define IS_DENORMAL(f) (((*(unsigned int *)&(f))&0x7f800000) == 0)
|
||||
|
||||
struct BiQuad
|
||||
{
|
||||
BiQuad() {}
|
||||
BiQuad(float dbGain, float freq, float srate, float bandwidthOrQ, bool isQ);
|
||||
|
||||
__declspec(align(16)) float a[4];
|
||||
BiQuad() {}
|
||||
BiQuad(float dbGain, float freq, float srate, float bandwidthOrQ, bool isQ);
|
||||
|
||||
__forceinline
|
||||
void removeDenormals()
|
||||
{
|
||||
if(IS_DENORMAL(x1))
|
||||
x1 = 0.0f;
|
||||
if(IS_DENORMAL(x2))
|
||||
x2 = 0.0f;
|
||||
if(IS_DENORMAL(y1))
|
||||
y1 = 0.0f;
|
||||
if(IS_DENORMAL(y2))
|
||||
y2 = 0.0f;
|
||||
}
|
||||
|
||||
__forceinline
|
||||
float process(float sample)
|
||||
{
|
||||
float result = a0 * sample + a[0] * x1 + a[1] * x2 +
|
||||
a[2] * y1 + a[3] * y2;
|
||||
|
||||
x2 = x1;
|
||||
x1 = sample;
|
||||
|
||||
y2 = y1;
|
||||
y1 = result;
|
||||
|
||||
//Input for next stage
|
||||
return result;
|
||||
}
|
||||
|
||||
__declspec(align(16)) float a[4];
|
||||
float a0;
|
||||
|
||||
float x1, x2;
|
||||
float y1, y2;
|
||||
};
|
||||
|
||||
struct ChannelData
|
||||
{
|
||||
ChannelData();
|
||||
|
||||
float preamp;
|
||||
unsigned filterCount;
|
||||
BiQuad filters[100];
|
||||
|
||||
// used while loading instead of overwriting immediately
|
||||
float loadPreamp;
|
||||
unsigned loadFilterCount;
|
||||
};
|
||||
|
||||
class ParametricEQ
|
||||
@@ -37,13 +85,14 @@ public:
|
||||
~ParametricEQ();
|
||||
|
||||
void setDeviceInfo(const std::wstring& deviceName, const std::wstring& connectionName, const std::wstring& deviceGuid);
|
||||
void initialize(float sampleRate, unsigned channelCount);
|
||||
void initialize(float sampleRate, unsigned channelCount, unsigned channelMask);
|
||||
void loadConfig();
|
||||
void process(float *output, float *input, unsigned frameCount);
|
||||
|
||||
private:
|
||||
void loadConfig(std::wstring path, unsigned& loadFilterCount, float& loadPreamp);
|
||||
void loadConfig(const std::wstring& path, std::vector<bool> selectedChannels);
|
||||
float getFreq(const std::wstring& freqString);
|
||||
unsigned getChannelNumber(unsigned position);
|
||||
static unsigned long __stdcall notificationThread(void* parameter);
|
||||
|
||||
std::wstring deviceName;
|
||||
@@ -52,10 +101,8 @@ private:
|
||||
std::wstring configPath;
|
||||
float sampleRate;
|
||||
unsigned channelCount;
|
||||
float preamp;
|
||||
BiQuad filters[100];
|
||||
unsigned filterCount;
|
||||
float sampleData[2000];
|
||||
unsigned channelMask;
|
||||
ChannelData* channelData;
|
||||
bool lastInputWasSilent;
|
||||
void* threadHandle;
|
||||
void* shutdownEvent;
|
||||
|
||||
Reference in new issue
Block a user