I've been finally able to add the portion of code to explain my question ...
I've recently upgraded my development PC and with it gcc from 4.1 to 4.8.
Compiling the same source I'm experiencing now a var overlap issue.
I can't post the entire cource since it is huge but just for understand I have some variables defined before the main() that are defined as extern on outside class so that can be accessed.
Someone of theese global variables change their value unexpectedly and debugging this with gdb I can see that this variable is sharing the same memory address as one member of a class instance.
This is the definition of variables on main.cpp the variable loopcounter is the only one I really need, I've surrounded it with unused variables in order to better understand this overlap.
uint64_t loopcounterx = 0;
uint64_t loopcounterxx = 0;
uint64_t loopcounterxxx = 0;
uint64_t loopcounterxxxx = 0;
uint64_t loopcounterxxxxx = 0;
uint64_t loopcounterxxxxxx = 0;
uint64_t loopcounter = 0;
uint64_t loopcountery = 0;
uint64_t loopcounteryy = 0;
uint64_t loopcounteryyy = 0;
uint64_t loopcounteryyyy = 0;
uint64_t loopcounteryyyyy = 0;
uint64_t loopcounteryyyyyy = 0;
uint64_t loopcounteryyyyyyy = 0;
.
.
.
int main(int argc, char *argv[]) {
I've set a watchdog for this variable write access with gdb
watch loopcounter
when the program execution stops I can see that we are inside an instance of the class Timer
Hardware watchpoint 1: loopcounter
Old value = 541
New value = 66077
Timer::signal (this=0xc235b0 (loopcounteryyy), s=true) at chrono.cpp:229
this is the portion of chrono.cpp
bool Timer::signal (bool s) {
if ((s != in_signal_old) && !r_pulse) {
in_signal = s;
if (s) in_signal_fp=true;
else in_signal_rp=true;
in_signal_old = s;
}
}
the watchdog stops the execution at line 229 of chrono.cpp which contains
if (s) in_signal_fp=true;
at the time of stop, the memory violation has already happened, so I think we must consider the line before, that is
in_signal = s;
where the code is accessing a member of it's class and it really seems that the writeing of this member will damage the content of loopcounter variable.
In fact, looking to pointers I get this
(gdb) p &loopcounter
$1 = (uint64_t *) 0xc235c8 (loopcounter)
(gdb) p &in_signal
$2 = (uint64_t *) 0xc235ca (loopcounter + 2)
(gdb) p &in_signal_fp
$5 = (bool *) 0xc235cc (loopcounter+4)
(gdb) p &active_f
$7 = (bool *) 0xc235c8 (loopcounter)
active_f is another member of the chrono class and it is perfectly overlapping the loopcounter variable.
this is the Timer class contained in chrono.h header
class Timer {
private:
Timer *me;
Timer *prev;
Timer *next;
bool active_f;
bool running_f;
bool in_signal;
bool in_signal_old;
bool in_signal_fp;
bool in_signal_rp;
bool out_signal;
bool out_signal_old;
bool out_signal_fp;
bool out_signal_rp;
bool f_pulse;
bool r_pulse;
uint64_t start;
uint64_t end;
uint64_t lenght;
timer_type type;
public:
int init (int lenght);
bool out (void);
bool active () { return active_f; }
bool fp () { return f_pulse; }
bool rp () { return r_pulse; }
bool running () { return running_f; }
void set_next (Timer *n) { next = n; }
void set_prev (Timer *p) { prev = p; }
void set_end (RTIME x) { end = x; }
void set_active (bool x) { active_f = x; }
void set_running (bool x) { running_f = x; }
void set_lenght (RTIME x) { lenght = x; }
void set_start (RTIME x) { start = x; }
void set_type (timer_type x) { type = x; }
void set_timer (RTIME x, timer_type y);// { lenght = x; type = y; }
bool signal (bool);
void set_fp (bool x) { f_pulse = x; }
void set_rp (bool x) { r_pulse = x; }
Timer * get_next () { return next; }
Timer * get_prev () { return prev; }
RTIME get_end () { return end; }
RTIME get_start () { return start; }
RTIME get_lenght (void) { return lenght; }
void append (Timer *newt);
Timer();
};
Why the compiler/linker or I don't know who else, is allocating two different objects on the same memory area ?
I've also used valgrind and the -fsanitize=address option introduced in gcc-4.8 but I can't get more useful informations or something more where to work on.
In which other way can I investigate over this behaviour ?
Related
I am trying to implement a vector using my own class so I can not do the initialiser list part
# include <iostream>
# include <exception>
# include<initializer_list>
template <class T>
class vector {
public:
T* a;
T n;
int pos, c;
vector() { a = 0; n = 0; }
vector(T n) : n(n) { a = new T[n]; }
vector(std::initializer_list <vector> l) {
a = new T[int(sizeof(l))];
for (int f : l)
*(a + f) = l.begin() + f;
}
void push_back(T k) {
int i = k;
*(a + n) = k;
}
vector& operator= (vector&& th) {
this->a = th.a;
th.a = nullptr; return (*this);
}
vector& operator=(vector& k)
{
this->a = k.a;
return(*this);
}
int size() { return n; }
void pop_back() { *(a + n) = nullptr;
n--;
}
void resize(int c) {
delete a;
n = c;
a = new T[c];
}
T operator[](int pos) {
if (pos > sizeof(a))
std::cout << "out of range";
else return *(a + pos);
}
};
int main() {
vector<int> a(10);
vector<char>b{ 'w','b','f','g' };
getchar();
return 0;
}
I am just trying to use pointer offset notation to take the initializer list items into the dynamic array but I get errors VS 17 IDE
Severity Code Description Project File Line Suppression
Error C2440 '=': cannot convert from 'const _Elem *' to 'T'
Error C2440 'initializing': cannot convert from 'const _Elem' to 'int'
Hello Nimrod!
#include <iostream>
#include <exception>
#include <initializer_list>
// normally people don't place a space between '#' and 'include'
template <class T>
class vector {
public:
T* a;
int n;
// probably it is length the vector
// change T to int
int pos, c;
vector() {
a = nullptr;
// do not use '0' to instruct null pointer
n = 0;
}
vector(int n): n(n) { a = new T[n]; }
vector(std::initializer_list<T> l) {
a = new T[l.size()];
// redundant force cast from size_t to int
for (int i = 0; i < l.size(); i++) {
a[i] = l.begin()[i];
}
// for (int f : l) # it seems that you wrote JavaScript before?
// *(a + f) = l.begin() + f;
}
void push_back(T k) {
// assigns "T k" to "int i"? it's confusing
// int i = k;
// *(a + n) = k;
}
// probably still many problems
vector& operator=(vector&& th) {
this->a = th.a;
th.a = nullptr;
return (*this);
}
vector& operator=(vector& k) {
this->a = k.a;
return(*this);
}
int size() { return n; }
void pop_back() { *(a + n) = nullptr;
n--;
}
void resize(int c) {
delete a;
n = c;
a = new T[c];
}
T operator[](int pos) {
if (pos > sizeof(a))
std::cout << "out of range";
else return *(a + pos);
}
};
int main() {
vector<int> a(10);
vector<char>b{ 'w','b','f','g' };
getchar();
return 0;
}
You still need more practice. XP
In your context of code, template variable for initializer_list should be T rather than int.
Range for loop with initializer_list<T> will fetch the values
in the list. Therefore it should belong to T.
In an attempt to make a more usable version of the code I wrote for an answer to another question, I used a lambda function to process an individual unit. This is a work in progress. I've got the "client" syntax looking pretty nice:
// for loop split into 4 threads, calling doThing for each index
parloop(4, 0, 100000000, [](int i) { doThing(i); });
However, I have an issue. Whenever I call the saved lambda, it takes up a ton of CPU time. doThing itself is an empty stub. If I just comment out the internal call to the lambda, then the speed returns to normal (4 times speedup for 4 threads). I'm using std::function to save the reference to the lambda.
My question is - Is there some better way that the stl library internally manages lambdas for large sets of data, that I haven't come across?
struct parloop
{
public:
std::vector<std::thread> myThreads;
int numThreads, rangeStart, rangeEnd;
std::function<void (int)> lambda;
parloop(int _numThreads, int _rangeStart, int _rangeEnd, std::function<void(int)> _lambda) //
: numThreads(_numThreads), rangeStart(_rangeStart), rangeEnd(_rangeEnd), lambda(_lambda) //
{
init();
exit();
}
void init()
{
myThreads.resize(numThreads);
for (int i = 0; i < numThreads; ++i)
{
myThreads[i] = std::thread(myThreadFunction, this, chunkStart(i), chunkEnd(i));
}
}
void exit()
{
for (int i = 0; i < numThreads; ++i)
{
myThreads[i].join();
}
}
int rangeJump()
{
return ceil(float(rangeEnd - rangeStart) / float(numThreads));
}
int chunkStart(int i)
{
return rangeJump() * i;
}
int chunkEnd(int i)
{
return std::min(rangeJump() * (i + 1) - 1, rangeEnd);
}
static void myThreadFunction(parloop *self, int start, int end) //
{
std::function<void(int)> lambda = self->lambda;
// we're just going to loop through the numbers and print them out
for (int i = start; i <= end; ++i)
{
lambda(i); // commenting this out speeds things up back to normal
}
}
};
void doThing(int i) // "payload" of the lambda function
{
}
int main()
{
auto start = timer.now();
auto stop = timer.now();
// run 4 trials of each number of threads
for (int x = 1; x <= 4; ++x)
{
// test between 1-8 threads
for (int numThreads = 1; numThreads <= 8; ++numThreads)
{
start = timer.now();
// this is the line of code which calls doThing in the loop
parloop(numThreads, 0, 100000000, [](int i) { doThing(i); });
stop = timer.now();
cout << numThreads << " Time = " << std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start).count() / 1000000.0f << " ms\n";
//cout << "\t\tsimple list, time was " << deltaTime2 / 1000000.0f << " ms\n";
}
}
cin.ignore();
cin.get();
return 0;
}
I'm using std::function to save the reference to the lambda.
That's one possible problem, as std::function is not a zero-runtime-cost abstraction. It is a type-erased wrapper that has a virtual-call like cost when invoking operator() and could also potentially heap-allocate (which could mean a cache-miss per call).
If you want to store your lambda in such a way that does not introduce additional overhead and that allows the compiler to inline it, you should use a template parameter. This is not always possible, but might fit your use case. Example:
template <typename TFunction>
struct parloop
{
public:
std::thread **myThreads;
int numThreads, rangeStart, rangeEnd;
TFunction lambda;
parloop(TFunction&& _lambda,
int _numThreads, int _rangeStart, int _rangeEnd)
: lambda(std::move(_lambda)),
numThreads(_numThreads), rangeStart(_rangeStart),
rangeEnd(_rangeEnd)
{
init();
exit();
}
// ...
To deduce the type of the lambda, you can use an helper function:
template <typename TF, typename... TArgs>
auto make_parloop(TF&& lambda, TArgs&&... xs)
{
return parloop<std::decay_t<TF>>(
std::forward<TF>(lambda), std::forward<TArgs>(xs)...);
}
Usage:
auto p = make_parloop([](int i) { doThing(i); },
numThreads, 0, 100000000);
I wrote an article that's related to the subject:
"Passing functions to functions"
It contains some benchmarks that show how much assembly is generated for std::function compared to a template parameter and other solutions.
In this game of life program the user tells the solve function how to access required data. Is it possible to be const-correct inside the function without supplying it with both const and non-const versions of data accessors? Clang complains about the constness of neighbor cell data when checking whether neighbors are alive or not (candidate function not viable: 1st argument ('const Cell') would lose const qualifier):
#include "array"
#include "iostream"
using namespace std;
struct Cell {
bool is_alive = false; int nr_live_neighs = 0;
};
template<
class Grid,
class Is_Alive_Getter,
class Nr_Live_Neighs_Getter
> void solve(
Grid& grid,
Is_Alive_Getter Is_Alive,
Nr_Live_Neighs_Getter Nr_Live_Neighs
) {
for (size_t i = 1; i < grid.size() - 1; i++) {
auto& cell = grid[i];
const auto // how to stay const-correct here?
&neigh_neg = grid[i - 1],
&neigh_pos = grid[i + 1];
if (Is_Alive(neigh_neg)) Nr_Live_Neighs(cell)++;
if (Is_Alive(neigh_pos)) Nr_Live_Neighs(cell)++;
}
for (auto& cell: grid) {
if (Nr_Live_Neighs(cell) == 3)
Is_Alive(cell) = true;
else if (Nr_Live_Neighs(cell) != 2)
Is_Alive(cell) = false;
Nr_Live_Neighs(cell) = 0;
}
}
int main() {
std::array<Cell, 10> grid;
for (size_t i = 0; i < grid.size(); i++) {
grid[i].is_alive = (i % 4 > 0);
}
solve(
grid,
[](Cell& cell_data) -> bool& {
return cell_data.is_alive;
},
[](Cell& cell_data) -> int& {
return cell_data.nr_live_neighs;
}
);
return 0;
}
I can use
if (Is_Alive(const_cast<decltype(cell)>(neigh_neg)))
instead of
if (Is_Alive(neigh_neg))
inside the solver but that feels hacky even though it doesn't seem to affect time to solution. What if a non-const reference isn't available to use in decltype? Is there a generic way to cast away the const by only referring to the const variable?
The common "solution" to use GetProcAddress with C++ is "extern "C", but that breaks overloading. Name mangling allows multiple functions to co-exist, as long as their signature differs. But is there a way to find these mangled names for GetProcAddress?
The VC++ compiler knows its own name mangling scheme, so why not use that? Inside template<typename T> T GetProcAddress(HMODULE h, const char* name), the macro __FUNCDNAME__ contains the mangled name of GetProcAddress. That includes the T part. So, inside GetProcAddress<void(*)(int), we have a substring with the mangled name of void(*)(int). From that, we can trivially derive the mangled name of void foo(int);
This code relies on the VC++ macro __FUNCDNAME__. For MinGW you'd need to base this on __PRETTY_FUNCTION__ instead.
FARPROC GetProcAddress_CppImpl(HMODULE h, const char* name, std::string const& Signature)
{
// The signature of T appears twice in the signature of T GetProcAddress<T>(HMODULE, const char*)
size_t len = Signature.find("##YA");
std::string templateParam = Signature.substr(0, len);
std::string returnType = Signature.substr(len+4);
returnType.resize(templateParam.size()); // Strip off our own arguments (HMODULE and const char*)
assert(templateParam == returnType);
// templateParam and returnType are _pointers_ to functions (P6), so adjust to function type (Y)
std::string funName = "?" + std::string(name) + "##Y" + templateParam.substr(2);
return ::GetProcAddress(h, funName.c_str());
}
template <typename T>
T GetProcAddress(HMODULE h, const char* name)
{
// Get our own signature. We use `const char* name` to keep it simple.
std::string Signature = __FUNCDNAME__ + 18; // Ignore prefix "??$GetProcAddress#"
return reinterpret_cast<T>(GetProcAddress_CppImpl(h, name, Signature));
}
// Showing the result
struct Dummy { };
__declspec(dllexport) void foo( const char* s)
{
std::cout << s;
}
__declspec(dllexport) void foo( int i, Dummy )
{
std::cout << "Overloaded foo(), got " << i << std::endl;
}
__declspec(dllexport) void foo( std::string const& s )
{
std::cout << "Overloaded foo(), got " << s << std::endl;
}
__declspec(dllexport) int foo( std::map<std::string, double> volatile& )
{
std::cout << "Overloaded foo(), complex type\n";
return 42;
}
int main()
{
HMODULE h = GetModuleHandleW(0);
foo("Hello, ");
auto pFoo1 = GetProcAddress<void (*)( const char*)>(h, "foo");
// This templated version of GetProcAddress is typesafe: You can't pass
// a float to pFoo1. That is a compile-time error.
pFoo1(" world\n");
auto pFoo2 = GetProcAddress<void (*)( int, Dummy )>(h, "foo");
pFoo2(42, Dummy()); // Again, typesafe.
auto pFoo3 = GetProcAddress<void (*)( std::string const& )>(h, "foo");
pFoo3("std::string overload\n");
auto pFoo4 = GetProcAddress<int (*)( std::map<std::string, double> volatile& )>(h, "foo");
// pFoo4 != NULL, this overload exists.
auto pFoo5 = GetProcAddress<void (*)( float )>(h, "foo");
// pFoo5==NULL - no such overload.
}
Use dumpbin /exports 'file.dll' to get the decorated / undecorated name of all the symbols.
It's impossible to do it just by using GetProcAddress. However, one way to do it would be to enumerate all the exported functions for that particular module, and do a pattern matching to find all the mangled names.
More specifically, refer to this answer here. The only change you will need to make would be to pass in TRUE for MappedAsImage parameter and the return value of GetModuleHandle for Base parameter to ImageDirectoryEntryToData function call.
void EnumerateExportedFunctions(HMODULE hModule, vector<string>& slListOfDllFunctions)
{
DWORD *dNameRVAs(0);
_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory;
unsigned long cDirSize;
_LOADED_IMAGE LoadedImage;
string sName;
slListOfDllFunctions.clear();
ImageExportDirectory = (_IMAGE_EXPORT_DIRECTORY*)
ImageDirectoryEntryToData(hModule,
TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &cDirSize);
if (ImageExportDirectory != NULL)
{
dNameRVAs = (DWORD *)ImageRvaToVa(LoadedImage.FileHeader,
LoadedImage.MappedAddress,
ImageExportDirectory->AddressOfNames, NULL);
for(size_t i = 0; i < ImageExportDirectory->NumberOfNames; i++)
{
sName = (char *)ImageRvaToVa(LoadedImage.FileHeader,
LoadedImage.MappedAddress,
dNameRVAs[i], NULL);
slListOfDllFunctions.push_back(sName);
}
}
}
I can't quite fathom why you'd ever want/need a constexpr version of MSalters' solution, but here it is, complete with namespace mangling. Use as
using F = int(double*);
constexpr auto f = mangled::name<F>([]{ return "foo::bar::frobnicate"; });
constexpr const char* cstr = f.data();
where F is the function signature and foo::bar::frobnicate is the (possibly qualified) name of the function.
#include<string_view>
#include<array>
namespace mangled
{
namespace detail
{
template<typename F>
inline constexpr std::string_view suffix()
{
auto str = std::string_view(__FUNCDNAME__);
return str.substr(14, str.size() - 87);
}
template<typename L>
struct constexpr_string
{
constexpr constexpr_string(L) {}
static constexpr std::string_view data = L{}();
};
template<typename Name>
inline constexpr int qualifiers()
{
int i = -2, count = -1;
while(i != std::string_view::npos)
{
i = Name::data.find("::", i + 2);
count++;
}
return count;
}
template<typename Name>
inline constexpr auto split()
{
std::array<std::string_view, qualifiers<Name>() + 1> arr = {};
int prev = -2;
for(int i = arr.size() - 1; i > 0; i--)
{
int cur = Name::data.find("::", prev + 2);
arr[i] = Name::data.substr(prev + 2, cur - prev - 2);
prev = cur;
}
arr[0] = Name::data.substr(prev + 2);
return arr;
}
template<typename F, typename Name>
struct name_builder
{
static constexpr auto suf = detail::suffix<F>();
static constexpr auto toks = split<Name>();
static constexpr auto len = Name::data.size() + suf.size() - toks.size() + 6;
static constexpr auto str = [] {
std::array<char, len> arr = {};
arr[0] = '?';
int i = 1;
for(int t = 0; t < toks.size(); t++)
{
if(t > 0)
arr[i++] = '#';
for(auto c : toks[t])
arr[i++] = c;
}
arr[i++] = '#';
arr[i++] = '#';
arr[i++] = 'Y';
for(auto c : suf)
arr[i++] = c;
return arr;
}();
};
}
template<typename F, typename LambdaString>
inline constexpr std::string_view name(LambdaString)
{
using Cs = detail::constexpr_string<LambdaString>;
using N = detail::name_builder<F, Cs>;
return {N::str.data(), N::len};
}
}
GodBolt
My name's Antonio from Italy.
I'm trying to create an Audio Unit using xCode 3.2.6, starting from the example at
this link.
This is my first AU project, and I have no other examples to follow.
My project consists of an IIR notch filter. The algorithm I made works fine (I tested in on Matlab), but the AU doesn't work properly (tested on AU Lab). The .mp3 file sounds filtered, but something like a square wave (I suppose by ear) is overlapped with it.
The frequency of that noise seems to be proportional to the f0 parameter.
Here is the .cpp file code:
// Filtro.cpp
#include "Filtro.h"
#define pi 3.1415926535
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
COMPONENT_ENTRY(Filtro)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::Filtro
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Filtro::Filtro (AudioUnit component) : AUEffectBase (component) {
CreateElements ();
Globals () -> UseIndexedParameters (kNumberOfParameters);
SetParameter (kParameter_Gain, kDefaultValue_Gain);
SetParameter (kParameter_f0, kDefaultValue_f0);
SetParameter (kParameter_Q, kDefaultValue_Q);
// code for setting default values for the audio unit parameters
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::GetParameterInfo
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma mark ____Parameters
ComponentResult Filtro::GetParameterInfo (
AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
AudioUnitParameterInfo &outParameterInfo
) {
ComponentResult result = noErr;
outParameterInfo.flags = kAudioUnitParameterFlag_IsWritable
| kAudioUnitParameterFlag_IsReadable;
if (inScope == kAudioUnitScope_Global) {
switch (inParameterID) {
case kParameter_Gain:
AUBase::FillInParameterName (
outParameterInfo,
kParamName_Gain,
false
);
outParameterInfo.unit = kAudioUnitParameterUnit_Decibels;
outParameterInfo.minValue = kMinimumValue_Gain;
outParameterInfo.maxValue = kMaximumValue_Gain;
outParameterInfo.defaultValue = kDefaultValue_Gain;
break;
case kParameter_f0: // 9
AUBase::FillInParameterName (
outParameterInfo,
kParamName_f0,
false
);
outParameterInfo.unit = kAudioUnitParameterUnit_Hertz;
outParameterInfo.minValue = kMinimumValue_f0;
outParameterInfo.maxValue = kMaximumValue_f0;
outParameterInfo.defaultValue = kDefaultValue_f0;
outParameterInfo.flags |= kAudioUnitParameterFlag_DisplayLogarithmic;
break;
case kParameter_Q: // 9
AUBase::FillInParameterName (
outParameterInfo,
kParamName_Q,
false
);
outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
outParameterInfo.minValue = kMinimumValue_Q;
outParameterInfo.maxValue = kMaximumValue_Q;
outParameterInfo.defaultValue = kDefaultValue_Q;
outParameterInfo.flags |= kAudioUnitParameterFlag_DisplayLogarithmic;
break;
default:
result = kAudioUnitErr_InvalidParameter;
break;
}
} else {
result = kAudioUnitErr_InvalidParameter;
}
return result;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::GetPropertyInfo
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus Filtro::GetPropertyInfo ( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 &outDataSize,
Boolean &outWritable)
{
return AUEffectBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::GetProperty
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus Filtro::GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void *outData )
{
return AUEffectBase::GetProperty (inID, inScope, inElement, outData);
}
#pragma mark ____FiltroEffectKernel
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::FiltroKernel::FiltroKernel()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Filtro::FiltroKernel::FiltroKernel (AUEffectBase *inAudioUnit) :
AUKernelBase (inAudioUnit), mSamplesProcessed (0), mCurrentScale (0) // 1
{
mSampleFrequency = GetSampleRate ();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::FiltroKernel::Reset()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Filtro::FiltroKernel::Reset() {
mCurrentScale = 0;
mSamplesProcessed = 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::FiltroKernel::Process
void Filtro::FiltroKernel::Process (const Float32 *inSourceP,
Float32 *inDestP,
UInt32 inSamplesToProcess,
UInt32 inNumChannels,
bool &ioSilence
) {
if (!ioSilence) {
const Float32 *sourceP = inSourceP;
Float32 *destP = inDestP, inputSample, outputSample;
Float32 Fs= mSampleFrequency;
int f0;
float w0, alpha, b0, b1, b2, a0, a1, a2;
float gain, dBgain, Q, coeff[5], x[5]={0,0,0,0,0} , out = 0;
dBgain = GetParameter (kParameter_Gain); //Get parameter from interface
if (dBgain < kMinimumValue_Gain) dBgain = kMinimumValue_Gain; //Check the right range
if (dBgain > kMaximumValue_Gain) dBgain = kMaximumValue_Gain;
f0 = GetParameter (kParameter_f0);
if (f0 < kMinimumValue_f0) f0 = kMinimumValue_f0;
if (f0 > kMaximumValue_f0) f0 = kMaximumValue_f0;
Q = GetParameter (kParameter_Q);
if (Q < kMinimumValue_Q) Q = kMinimumValue_Q;
if (Q > kMaximumValue_Q) Q = kMaximumValue_Q;
w0 = 2*pi*f0/Fs;
alpha = sin(w0)*sinh(log(2)/(log(exp(1))*2) * Q * w0/sin(w0));
b0 = 1;
b1 = -2*cos(w0);
b2 = 1;
a0 = 1 + alpha;
a1 = -2*cos(w0);
a2 = 1 - alpha;
coeff[0] = b0/a0;
coeff[1] = b1/a0;
coeff[2] = b2/a0;
coeff[3] = -a1/a0;
coeff[4] = -a2/a0;
//----------------------------------------------------------------------------------------------//
// y(n) = b0/a0 * x(n) + b1/a0 * x(n-1) + b2/a0 * x(n-2) * -a1/a0 * y(n-1) * -a2/a0 * y(n-2) //
//----------------------------------------------------------------------------------------------//
for (int i = inSamplesToProcess; i > 0; --i) {
int index = static_cast<long>(mSamplesProcessed * mCurrentScale) % 512; //?
if ((mNextScale != mCurrentScale) && (index == 0)) { //??
mCurrentScale = mNextScale;
mSamplesProcessed = 0;
}
if ((mSamplesProcessed >= sampleLimit) && (index == 0)) { // ??
mSamplesProcessed = 0;
}
gain = pow(10, dBgain/20);
inputSample = *sourceP;
x[0] = inputSample; //x(n)
x[3] = outputSample; //y(n-1)
for (int h = 0; h < 5; h++) { // Processing output sample
out = out+x[h]*coeff[h];
}
for (int h = 4; h > 0; h--) {
x[h]=x[h-1]; //I/O array shifting
}
outputSample = out * gain;
out = 0;
*destP = outputSample;
sourceP += 1;
destP += 1;
mSamplesProcessed += 1;
}
}
}
And that's the header file:
// Filtro.h
#include "AUEffectBase.h"
#include "AUEffectBase.h"
#include "FiltroVersion.h"
#if AU_DEBUG_DISPATCHER
#include "AUDebugDispatcher.h"
#endif
#ifndef __Filtro_h__
#define __Filtro_h__
#pragma mark ____Filtro Parameter Constants
static CFStringRef kParamName_Gain = CFSTR ("Gain");
static const double kDefaultValue_Gain = 0;
static const double kMinimumValue_Gain = -40;
static const double kMaximumValue_Gain = 0;
static CFStringRef kParamName_f0 = CFSTR ("f0");
static const int kDefaultValue_f0 = 1048;
static const int kMinimumValue_f0 = 50;
static const int kMaximumValue_f0 = 20000;
static CFStringRef kParamName_Q = CFSTR ("Q");
static const double kDefaultValue_Q = 0.1;
static const double kMinimumValue_Q = 0.001;
static const double kMaximumValue_Q = 10;
// parameter identifiers
enum { // Defines constants for identifying the parameters; defines the total number of parameters
kParameter_Gain = 0,
kParameter_f0 = 1,
kParameter_Q = 2,
kNumberOfParameters = 3
};
#pragma mark ____Filtro
class Filtro : public AUEffectBase
{
public:
Filtro(AudioUnit component);
#if AU_DEBUG_DISPATCHER
virtual ~Filtro () { delete mDebugDispatcher; }
#endif
virtual AUKernelBase * NewKernel() { return new FiltroKernel(this); }
virtual OSStatus GetParameterInfo(AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
AudioUnitParameterInfo &outParameterInfo);
virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable );
virtual OSStatus GetProperty(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);
virtual bool SupportsTail () { return false; } // FIND
/*! #method Version */
virtual OSStatus Version() { return kFiltroVersion; }
// virtual ComponentResult GetPresets (CFArrayRef *outData) const;
// virtual OSStatus NewFactoryPresetSet (const AUPreset &inNewFactoryPreset);
protected:
class FiltroKernel : public AUKernelBase {
public:
FiltroKernel (AUEffectBase *inAudioUnit); // 1
virtual void Process (
const Float32 *inSourceP,
Float32 *inDestP,
UInt32 inFramesToProcess,
UInt32 inNumChannels, // equal to 1
bool &ioSilence
);
virtual void Reset();
private:
Float32 mSampleFrequency;
long mSamplesProcessed;
enum {sampleLimit = (int) 10E6};
float mCurrentScale;
float mNextScale;
};
};
#endif#include "FiltroVersion.h"
#if AU_DEBUG_DISPATCHER
#include "AUDebugDispatcher.h"
#endif
#ifndef __Filtro_h__
#define __Filtro_h__
#pragma mark ____Filtro Parameter Constants
static CFStringRef kParamName_Gain = CFSTR ("Gain");
static const double kDefaultValue_Gain = 0;
static const double kMinimumValue_Gain = -40;
static const double kMaximumValue_Gain = 0;
static CFStringRef kParamName_f0 = CFSTR ("f0");
static const int kDefaultValue_f0 = 1048;
static const int kMinimumValue_f0 = 50;
static const int kMaximumValue_f0 = 20000;
static CFStringRef kParamName_Q = CFSTR ("Q");
static const double kDefaultValue_Q = 0.1;
static const double kMinimumValue_Q = 0.001;
static const double kMaximumValue_Q = 10;
// parameter identifiers
enum { // Defines constants for identifying the parameters; defines the total number of parameters
kParameter_Gain = 0,
kParameter_f0 = 1,
kParameter_Q = 2,
kNumberOfParameters = 3
};
#pragma mark ____Filtro
class Filtro : public AUEffectBase
{
public:
Filtro(AudioUnit component);
#if AU_DEBUG_DISPATCHER
virtual ~Filtro () { delete mDebugDispatcher; }
#endif
virtual AUKernelBase * NewKernel() { return new FiltroKernel(this); }
virtual OSStatus GetParameterInfo(AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
AudioUnitParameterInfo &outParameterInfo);
virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable );
virtual OSStatus GetProperty(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);
virtual bool SupportsTail () { return false; }
/*! #method Version */
virtual OSStatus Version() { return kFiltroVersion; }
protected:
class FiltroKernel : public AUKernelBase {
public:
FiltroKernel (AUEffectBase *inAudioUnit);
virtual void Process (
const Float32 *inSourceP,
Float32 *inDestP,
UInt32 inFramesToProcess,
UInt32 inNumChannels, // equal to 1
bool &ioSilence
);
virtual void Reset();
private:
Float32 mSampleFrequency;
long mSamplesProcessed;
enum {sampleLimit = (int) 10E6};
float mCurrentScale;
float mNextScale;
};
};
#endif
Thank a lot. I hope my English is not too bad.
Your filter implementation does not look correct to me. Maybe it's fine, but it's hard to follow. For example, it looks like you are shifting your stored x values into your stored y values, and even though you clear that up on the next loop, it's all a bit hard to follow.
You might want to check out how I do it here: http://blog.bjornroche.com/2012/08/basic-audio-eqs.html Much cleaner!
Also, are you processing mono samples or multichannel audio, because your Process function looks like it will only work as you intend with mono audio. (I haven't worked with AU's recently enough to be able to answer this myself from looking at your code)
Problem solved!!! After 3 days, I found the right way to avoid the variables reset every audio frame. I just declared those state variables into the Filtro.h file at the fourth line from the bottom, and than I initialised them into the "AUKernelBase (inAudioUnit)" in Filtro.cpp file. I hope it can be helpful to other people. Bye.