A Collection of Useful C++ Classes for Signal Processing

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

thevinn wrote:
Caco wrote:**Edit - the demo binary isn't working here, I get an error message saying the application is configured incorrectly and may need reinstalling..
UGH, I linked it with "Multithreaded DLL". I will relink it and upload it again...sorry!!!

Okay I re-uploaded a new one, v.0.8.6.1 please let me know if it works.

Thanks!
Works great :tu:

Post

hi thevinn

as i mentioned already, i got some compiler errors within msvc express. i now tryed again with msvc2008 professional edition and allmost everything works fine. so you may check why this won't work with the express edition, or explain how to setup for youre DSPFilter's.

now i still get an error:

1>d:\dokumente\c++\ueb\c++\antialias\src\processor.cpp(113) : error C2664: 'Dsp::PoleFilterSpace<Proto,Trans,maxorder,channels>::Setup' : cannot convert parameter 1 from 'double' to 'const Dsp::Spec &'
1> with
1> [
1> Proto=Dsp::Butter,
1> Trans=Dsp::LowPass,
1> maxorder=2,
1> channels=1
1> ]
1> Reason: cannot convert from 'double' to 'const Dsp::Spec'
1> No constructor could take the source type, or constructor overload resolution was ambiguous

do anybody know why this happen?

cheers pascal

Post

Are you saying that it works in Visual Studio 2008 Professional but not Visual Studio 2008 Express?

Post

yes, exactly! may it takes some configuration for the express edition like for the juce framework?

but the one error i mentioned, occures at the pro edition. so it won't work for me either with the pro nor with the express. the difference is just about ca. 30 more errors with the express edition! (please have a look at page 4 or 5 in this topic where i posted this)

cheers pascal

Post

BRP wrote:yes, exactly! may it takes some configuration for the express edition like for the juce framework?
I don't see any reason why Express would be different from Professional. There are no project-specific settings required to get the Juce demo application compiled. It should be possible to simply create a default Windows application project, add the sources in, compile, and link.
but the one error i mentioned, occures at the pro edition.
so it won't work for me either with the pro nor with the express. the difference is just about ca. 30 more errors with the express edition! (please have a look at page 4 or 5 in this topic where i posted this)
Page 4/5 of this topic refers to an older version of DspFilters. The latest one is available here:

http://code.google.com/p/dspfilterscpp/

This one should work for you. I rewrote the entire class hierarchy and pushed the templates down to the most derived class. This is what was causing the problem in the old version. Technically speaking, MSVC does type checking at the moment of template instantiation, while gcc does its preliminary checking at the time it sees the declaration. This difference is what caused the mountain of compile time errors.

In order to make sure that this thing worked, I saw to it that the new code compiles under g++ using Code:Blocks. The project has been tested, compiled, and executed under Code:Blocks with g++, and MS Visual Studio 2008 Professional.

Code: Select all

1>d:\dokumente\c++\ueb\c++\antialias\src\processor .cpp(113) : error C2664: 'Dsp::PoleFilterSpace<Proto,Trans,maxorder,channel s>::Setup' : cannot convert parameter 1 from 'double' to 'const Dsp::Spec &' 
processor.cpp is not one of the files in the DspFilters distribution. Is this your own file? Can you paste the declaration and point of call please? What is the error that you get when compiling DspJuceDemo.cpp in the DspFilters distribution?

If your call to setup doesn't work try something like this:

Code: Select all

Dsp::ButterLowPass<10,2> f; // max order 10, channels = 2

f.PoleFilter::Setup( spec ); // note the qualified name

Post

please take a look to the installnotes of juce for the express edition. you have to install the platform sdk and do some other stuff explained there. i don't know why either! but i'm, as i mentioned, just a newbe at coding.. you may could ask this in the juce forum, where you'll get some good explanation for sure.

cheers pascal

Post

this is my implementation, did i make anything wrong?

Code: Select all

void Processor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
	if (mainProcessIn == 1)
	{
		OSFactor = 1 + mainOverSampling * 63;
		mainSampleRate = getSampleRate ();
		mainBufferSize = buffer.getNumSamples ();
		processedBuffer->setSize (2, mainBufferSize*OSFactor);
		downSampledBuffer->setSize (2, mainBufferSize);

		
		
		int j = 0;
		
		int cursor1 = 0;
		int cursor2 = 0;

		inputBufferL = new float[mainBufferSize];
		inputBufferR = new float[mainBufferSize];
		processedBufferL = new float[mainBufferSize*OSFactor];
		processedBufferR = new float[mainBufferSize*OSFactor];

			
		for (int i = 0; i < mainBufferSize; ++i) 
		{
			inputBufferL[cursor1] = *buffer.getSampleData(0, i);
			inputBufferR[cursor1] = *buffer.getSampleData(1, i);
			cursor1++;
			if (cursor1 >= mainBufferSize) cursor1 = 0; 
		}

		OS->oversample (buffer, mainBufferSize, OSFactor);
		processedBuffer = OS->OSBuffer;

		processedBuffer->applyGain (0, 0, mainBufferSize*OSFactor, mainVolume);
		processedBuffer->applyGain (1, 0, mainBufferSize*OSFactor, mainVolume);
		
		float *samples0 = processedBuffer->getSampleData(0, j);
		float *samples1 = processedBuffer->getSampleData(1, j);
		
		for (j = 0; j < mainBufferSize*OSFactor; ++j) 
		{
			processedBufferL[cursor2] = *samples0;
			processedBufferR[cursor2] = *samples1;
			samples0++;
			samples1++;
			cursor2++;
					
			if (cursor2 >= mainBufferSize*OSFactor) cursor2 = 0; 
		}

/*	
		filterL1->makeLowPass (mainSampleRate*OSFactor, freq*20000.f);
		filterL1->processSamples (processedBufferL, mainBufferSize*OSFactor);
		filterL2->makeLowPass (mainSampleRate*OSFactor, freq*20000.f);
		filterL2->processSamples (processedBufferL, mainBufferSize*OSFactor);
		filterL3->makeLowPass (mainSampleRate*OSFactor, freq*20000.f);
		filterL3->processSamples (processedBufferL, mainBufferSize*OSFactor);
		filterR1->makeLowPass (mainSampleRate*OSFactor, freq*20000.f);
		filterR1->processSamples (processedBufferR, mainBufferSize*OSFactor);
		filterR2->makeLowPass (mainSampleRate*OSFactor, freq*20000.f);
		filterR2->processSamples (processedBufferR, mainBufferSize*OSFactor);
		filterR3->makeLowPass (mainSampleRate*OSFactor, freq*20000.f);
		filterR3->processSamples (processedBufferR, mainBufferSize*OSFactor);
*/	
	
		
		
		Dsp::ButterLowPass<2,1> f[2];
		f[0].Setup (freq*20000./(mainSampleRate*OSFactor));
		f[1].Setup (freq*20000./(mainSampleRate*OSFactor));
		f[0].Process (mainBufferSize*OSFactor, processedBufferL);
		f[1].Process (mainBufferSize*OSFactor, processedBufferR);
	
		
		processedBuffer->copyFrom (0, 0, processedBufferL, mainBufferSize*OSFactor);
		processedBuffer->copyFrom (1, 0, processedBufferR, mainBufferSize*OSFactor);

		

		OS->downsample (*processedBuffer, mainBufferSize, OSFactor);
		downSampledBuffer = OS->DSBuffer;



		

		downSampledBuffer->addFrom (0, 0, inputBufferL, mainBufferSize, mainDryWet);
		downSampledBuffer->addFrom (1, 0, inputBufferR, mainBufferSize, mainDryWet);



		
		buffer = AudioSampleBuffer (*downSampledBuffer);



		delete inputBufferL;
		delete inputBufferR;
		delete processedBufferL;
		delete processedBufferR;
	}
    
    //==========================================================================
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }
}
cheers pascal

Post

Code: Select all

      Dsp::ButterLowPass<2,1> f[2];
      f[0].Setup (freq*20000./(mainSampleRate*OSFactor));
      f[1].Setup (freq*20000./(mainSampleRate*OSFactor));
Because of the way that g++ handles templates, it is not possible for two versions of Setup() to co-exist peacefully. I renamed the version of Setup() that operates on a set of parameters instead of the Spec structure, to SetupAs().

So change it to:

Code: Select all

      f[0].SetupAs (freq*20000./(mainSampleRate*OSFactor));
      f[1].SetupAs (freq*20000./(mainSampleRate*OSFactor));
And it should work.

Post

hi thevinn

thanks a lot! i'll try right now..

cheers pascal

Post

hi thevinn

it compiles now very well.. but when i check my plugin, i get some crackle noise as soon as i lower the frequency of the filter below about 1000 Hz. i can't say exactly, because i listen through the laptop speakers.. it seams like its crackling the more the lower the frequency. do you notice this as well, or did i implementing it wrong?

thanks for youre patience, and please let me know when i ask some stupid questions witch would just waste youre time!! i really thanks for youre great work and dont want you to do my homework! i just want to help and of course would love to use a wellworking DSPFilter.cpp :love:

cheers pascal

Post

Your implementation looks fine. If you hear crackling, or "zippering", while you are changing the frequency of the filter, that might be normal. But if you stop changing the cutoff frequency and you still hear some artifacts, that is definitely not a problem with DspFilter.cpp. I hope this helps you narrow your search for the bug.

Post

i still hear the artifacts after adjusting the cutoff and leave it alone.. but as you see, i implemented some juce filters as well and they work propper. could there be an incompatibility with the way the juce audio buffer handles the bufferdata? crackles could occure if some samples were left out..i can not imagin that this would happen, but i also have no other idea.. :(

did you once implement youre filter with juce?(of course you did for the DSPJuce, but i mean with processed audio)

cheers pascal

Post

hi thevinn

i found the bug. i implemented the filter just straight as you were showing at the examples. (called the filtertemplate in the processblock, so it was creating one each new block!) i had(and still have) a lack of understanding templates.

i now implemented it like this:

Code: Select all

processor.h
   Dsp::ButterLowPass<4,1> f[2];

processor.cpp
(constructor)
   Dsp::ButterLowPass<4,1> f[2];
   f[0].SetupAs (1.f);
   f[1].SetupAs (1.f);
(processblock)
   f[0].SetupAs (freq*20000.f/(mainSampleRate*OSFactor));
   f[1].SetupAs (freq*20000.f/(mainSampleRate*OSFactor));
   f[0].Process (mainBufferSize*OSFactor, processedBufferL);
   f[1].Process (mainBufferSize*OSFactor, processedBufferR);
and now it works fine.
may you want to explain a bit in youre examples how to use the templates for those who don't know?

cheers pascal

Post

BRP wrote:may you want to explain a bit in youre examples how to use the templates for those who don't know?
IMHO such explanations are outside the scope of thevinn's offering. At some point the code's function should be inferred from the code itself, with comments only where things are not obvious. For anything else (as in core language features) I would suggest a book on C++ programming, or some web tutorials. Get to know how the STL works, and try writing some template classes of your own.

http://www.cplusplus.com/doc/tutorial/templates/
http://www.sgi.com/tech/stl/

It's not that bad, really :)

Post

I'm not entirely happy with the usability or the readability of the class hierarchy but it was the best I could do for a first pass rewrite that compiled under g++.

I think that if the test application did some actual audio filtering it would serve as a sufficient example.

In the interest of full disclosure I am only this year finally getting around to learning templates, I've been pretty resistant to it. I think they were definitely helpful in this implementation, it was a nice way to separate the storage from the implementation, and without using operator new. It was also helpful for creating composite filter classes from the building blocks in a generic way.

The rewrite and test app were pretty exhausting but I will recover soon and fix the hard coded root finder and elliptic curve storage.

Any tips (hyperlinks?) for making the Bessel (or Legendere) work right are greatly appreciated.

Post Reply

Return to “DSP and Plugin Development”