Avatar

Please consider registering
Guest

sp_LogInOut Log In sp_Registration Register

Register | Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

sp_Feed sp_TopicIcon
Chapter 3 - Simple HPF Questions
No permission to create posts
July 11, 2017
5:04 pm
Avatar
SonicScholar
Member
Members
Forum Posts: 5
Member Since:
July 11, 2017
sp_UserOfflineSmall Offline

Hi everyone!

I am working through the book and have a few questions so far. So I am currently building the Tone Control plugin. . . 

float xn = pInputBuffer[0];

float xn_1 = m_f_z1;

yn = m_f_a0 * xn + m_f_a1 * xn_1;

m_f_z1 = xn;

pOutputBuffer[0] = yn;

Why dont we just assign the output buffer to a0 * xn + a1 * xn-1? Like pOutputBuffer[0] = m_f_a0 * xn + m_f_a1  xn_1. Why do we need to make the yn variable? Is it purely to assist in the way we express the difference equation by code?

Also, why cant we share coefficients for editable parameters? In this case, a1 is the same value for each channel. Am I correct to say that a1 in this case can be used for each channel (as it does not contain 'significant' information, rather static float values that are not dependant on each channel - unlike z1 which is different on each channel, and therefore we would need 2 for stereo)?

٩(̾●̮̮̃̾•̃̾)۶

July 12, 2017
12:23 pm
Avatar
W Pirkle
Admin
Forum Posts: 143
Member Since:
January 28, 2017
sp_UserOfflineSmall Offline

Why dont we just assign the output buffer to a0 * xn + a1 * xn-1? Like pOutputBuffer[0] = m_f_a0 * xn + m_f_a1  xn_1. Why do we need to make the yn variable? Is it purely to assist in the way we express the difference equation by code?

You absolutely can simply compute the output directly. Many of the examples in the book use verbose, rather then terse, coding and can be reduced/made more efficient. The reason is that in most other DSP books, they do the exact opposite, and for really complex algorithms it can be confusing. That's all. In addition that equation yn = ... exactly matches the difference equation - something else to try to make things simple.

Also, why cant we share coefficients for editable parameters? In this case, a1 is the same value for each channel. Am I correct to say that a1 in this case can be used for each channel (as it does not contain 'significant' information, rather static float values that are not dependant on each channel - unlike z1 which is different on each channel, and therefore we would need 2 for stereo)?

Yes, of course you can share similar variables. However as a general rule, I try to keep multi-channel algorithms separate with respect to all their block diagrams and attributes during development. Then, when debugging is completed, you can improve the algorithms by sharing variables, etc... again, trying to keep things simple and obvious at first. In some 5.1 algorithms, I've used different filters on different channels to achieve certain effects. 

I have been burned too many times in the past, where I tried to compact the code (or "kaizen" it to use a Japanese term) when I first coded it - especially with really complex algorithms -  then spent more time trying to debug my code than I would have spent if I just started with verbose code first, then after debugging was complete, compacted it one step at a time. That's just my personal experience and philosophy and you can surely ignore that development routine if you want. 

And, yes you are correct about the state variables (the z^-1 registers) which can not be shared across channels. 

- Will

July 12, 2017
2:21 pm
Avatar
SonicScholar
Member
Members
Forum Posts: 5
Member Since:
July 11, 2017
sp_UserOfflineSmall Offline

Thanks Will!

I appreciate the reasons why you use quite direct interpretations to help understand what we are doing in c++. I prefer to use this method as well, and I can see the benefits when designing quite complex plugins. I am happy that this is the case! No doubt it an be frustrating to review your projects at later stages, and have to remember some abstract design SmileI have a further question on the design

So when we calculate a0:

m_f_a0  = m_f_a1 - 1.0;

Why do we do this both in the constructor AND userInterfaceChanged? I understand why we add it in userInterfaceChanged (UI updates). Cant we just leave it out of the constructor and set each variable to a float? My understanding of the constructor is like an initialization procedure run before the main block. Used to set variables and and constants? In the book, just before you write. . .

3.11.4 SimpleHPF.cpp File

Constructor

- Set our coefficient values to match the initialized slider settings

- Calculate the new a0 values

- Clear out the z-1 variables

Can we set out a0 value to -1 for instance, instead of doing the calculation again? Because we know what the slider init value is (0 and take away 1 for the equation), and when the user moves the slider our userInterfaceChanged function runs to update it, why do we do it this way? If that line is to set the a0 coefficient, are we doing extra work by calculating it again?

Finally, want to say thanks for writing the book! Its like my bible, and dont worry, I'll never let my cat chew on it!

Kiss

٩(̾●̮̮̃̾•̃̾)۶

July 12, 2017
2:59 pm
Avatar
W Pirkle
Admin
Forum Posts: 143
Member Since:
January 28, 2017
sp_UserOfflineSmall Offline

 Can we set out a0 value to -1 for instance, instead of doing the calculation again? 

Sure - but the constructor is only called once - it is the "one time init" function and the old-fashioned C++ programmer in me is pretty firm about making sure the plugin is in a perfectly initialized state after construction, and matching the UI. Since it is only called once, at construction time, and before any audio streams, there's no loss of efficiency. But, yeah you can certainly make that simplification. 

One of the other admins on this Forum has similar feelings about that as I do - there is a thread somewhere about constructor initialization and coding practices. For example, we both do something similar with pointers:

member variable: float* m_pData; <-- .h file

in constructor:

m_pData = NULL;

m_pData = new float[1024];

Some would say that you don't need that first line m_pData = NULL since the very next line of code overwrites the pointer, but many seasoned programmers will still do this... NOTE: C++11 rocks in that you can initialize variables in the .h file directly and my new books will be using this kind of initialization; at the time the FX book went to print, not all compilers dealt with C++11 completely (VS2008 and VS2010 had no support at all, and VS2012 only supported a subset of C++11 extensions) so I chose to keep the C++ in an older, pre C++11 format, knowing that some would balk at it anyways... Just a side-note there.

- Will

July 12, 2017
4:20 pm
Avatar
SonicScholar
Member
Members
Forum Posts: 5
Member Since:
July 11, 2017
sp_UserOfflineSmall Offline

Hahaha, old habits die hard I suppose Laugh

When you say 'new books', are they reprints with updates or vol.3 and vol.4 in the series?

٩(̾●̮̮̃̾•̃̾)۶

July 13, 2017
10:09 am
Avatar
W Pirkle
Admin
Forum Posts: 143
Member Since:
January 28, 2017
sp_UserOfflineSmall Offline

Can't say anything just yet as no contract has been signed.

Forum Timezone: America/New_York

Most Users Ever Online: 36

Currently Online:
2 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

Skyler: 47

Peter: 41

Derek: 41

clau_ste: 39

Frodson: 38

Gwen: 32

EZB: 24

lppier: 23

Msaldaña: 18

Jorge: 17

Member Stats:

Guest Posters: 1

Members: 476

Moderators: 1

Admins: 4

Forum Stats:

Groups: 11

Forums: 30

Topics: 482

Posts: 1876

Newest Members:

sam, annaharris, Marie Weaver, kev, Steven, Mr Anderson, mguy, omelc

Moderators: W Pirkle: 143

Administrators: Tom: 65, JD Young: 80, Will Pirkle: 0, W Pirkle: 143