I'm using the code from this article https://www.mql5.com/en/articles/159 to calculate when a new bar opens but it's not displaying the historical data for the indicator.
I have modified the TimeCurrent() to iTime( _Symbol, _Period, shift ) so as to try to handle this, but it's not working.
Could you tell me what I'm doing wrong please?
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 RoyalBlue
#include <Lib_CisNewBar.mqh>
CisNewBar current_chart;
//---- input parameters
extern int Length=18; // Bollinger Bands Period
extern int Deviation=2; // Deviation was 2
extern double MoneyRisk=1.00; // Offset Factor
extern int Signal=1; // Display signals mode: 1-Signals & Stops; 0-only Stops; 2-only Signals;
extern int Line=1; // Display line mode: 0-no,1-yes
extern int Nbars=1000;
//---- indicator buffers
double TrendBuffer[];
extern bool SoundON=true;
bool TurnedUp = false;
bool TurnedDown = false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
string short_name;
//---- indicator line
SetIndexBuffer(0,TrendBuffer);
SetIndexStyle(0,DRAW_LINE,0,1);
IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
short_name="Example ("+Length+","+Deviation+")";
IndicatorShortName(short_name);
SetIndexLabel(0,"Trend Value");
//----
SetIndexDrawBegin(0,Length);
//----
return(INIT_SUCCEEDED);
}
void deinit()
{
}
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
int shift;
for (shift=Nbars;shift>=0;shift--)
{
TrendBuffer[shift]=0;
}
for (shift=Nbars-Length-1;shift>=0;shift--)
{
int period_seconds=PeriodSeconds(_Period);
datetime new_time=iTime(_Symbol,_Period,shift)/period_seconds*period_seconds;
if(current_chart.isNewBar(new_time))
{
Print("time[shift] = "+TimeToString(time[shift]));
if( Close[shift] > Close[shift+1] )
TrendBuffer[shift]=1;
else if(Close[shift] < Close[shift+1] )
TrendBuffer[shift]=-1;
else
TrendBuffer[shift]=0;
}
}
return(0);
}
Thanks.
a) The "new"-MQL4.56789 has another syntax
For Custom Indicator, the "new"-MQL4.56789 source shall rather read
void OnInit(){ ... }andvoid OnDeinit( const int anMT4_Reason2callDeinit ){ ... }
b) The datetime
Your code defines a variable new_time, typed as a datetime
The datetime type is intended for storing the date and time as the number of seconds elapsed since January 01, 1970.
and
Values range from 1 January, 1970 to 31 December, 3000
So, in case of your new_time assignment, the proper iTime() value is divided by an amount of PeriodSeconds() and right next it is re-multiplied by the exact same value, which should not change the value of the iTime() result.
Such operation, while having no theoretical impact on result, might in practice of a code-execution introduce a risk of a numerical inaccuracy, range overflow/underflow and a theoretical notice about a resolution of an 8-byte class storage is not helping to go past the upper bound limit, stated in the documentation as Dec-31, 3000.
In similar cases unpredicatable results and even MT4 unhandled exceptions and MQL4-code terminations are to be expected.
What worse one may expect for a production grade software? So, avoid, avoid and avoid any such risk.
There is no direct positive value for such a Custom Indicator calculation step.
c) TimeCurrent() / PeriodSeconds() side-effect of rounding
While iTime() is always divisible by it's "own" time-frame PeriodSeconds(), TimeCurrent() is not.
Thus one may read the original ( assumed ) construct of
TimeCurrent() / PeriodSeconds() // .DIV is subject to rounding to int
* PeriodSeconds(); // before the forthcoming .MUL
"hacks" the need to align a [last known server time, time of the last quote receipt for one of the symbols selected in the "Market Watch" window] to one's "own" time-frame value of a start-of-current bar time.
d) The article is from 11 October 2010 (!) - be very carefull in MQL4
Current MQL4 code-execution engine is Build 890 ( 25 Sep 2015 ), so your cited source was using an MQL5 language syntax some 5 years old (!!), which namely in MQL4-domain means _be_very_carefull_
In the meantime string-s ceased to be string-s,
many GUI functions have several calling protocols in parallel,
andcountless man*years of DLL/API-code-base dev/maint were lost due to similar moving sands.
So -5- years gap is a warning per-se.
One never enters the same river twice
The recent state of "new"-MQL4.56789 allows a clean approach:
in case your motivation is just to be able to detect on-demand a situation a new bar has started, the Build-890/1174 compiler allows for a cleaner approach:
bool aNewBarEVENT( const string anFxSYMBOL, // _Symbol,
const int aTimeFRAME // PERIOD_M6
)
{ static int pBars = EMPTY; // previous
int oBars = iBars( anFxSYMBOL, aTimeFRAME ); // observed
if ( pBars == oBars ) return( False ); // .NACK
pBars = oBars, return( True ); // .UPD + .ACK
}
Related
MISRA C 2012 Directive 4.1 says that Run-time failures should be minimized and further states for pointer dereferencing that a pointer should be checked for NULL before it's dereferenced,
unless it's already known to be not NULL.
When writing a library performing simple operations, checking the input pointers in each library function
for NULL creates larger and therefore less understandable code even for simple operations.
For example below library computes the squared euclidian norm of a vector and gets used in a controller
/*** Option 1: Checking pointers ***/
Library:
/* file vector.c */
bool_t bVectorNormSq(float32_t pf32Vec[], uint8_t u8Len, float32_t *pf32NormSq)
{
uint8_t u8n;
bool bRet = false;
/* Check pointers */
if( (pf32Vec != NULL) && (pf32NormSq != NULL) )
{
*pf32NormSq = 0.0f;
for(u8n = 0U; u8n < u8Len; u8n++)
{
*pf32NormSq += (pf32Vec[u8n] * pf32Vec[u8n]);
}
bRet = true;
}
else
{
/* Do not alter pf32NormSq (unknown if valid pointer) */
bRet = false;
}
return bRet;
}
/* EOF */
Consumer of library:
/* file controller.c */
/* ... */
bool_t bControllerStep(void)
{
float32_t pf32MyVec[3] = { 0 };
float32_t f32MyNorm = 0.0f;
/* ... */
/* MISRA C 2012 Rule 17.7, Call will always be successful, thus return value not checked */
(void)bVectorNormSq(pf32MyVec, 3U, &f32MyNorm);
/* ... */
}
/* EOF */
/*** Option 2: Not checking pointer, responsibility to supply valid inputs placed on caller ***/
Library:
/* file vector.c */
/**
* #note This library assumes that valid pointers will be supplied,
* pointers are NOT checked before they are used.
*/
/* Assert macro expands to "(void)(CONDITION)" for NDEBUG defined */
#ifdef NDEBUG
VECTOR_ASSERT( CONDITION ) (void)(CONDITION)
#else
/* ... */
#endif /* NDEBUG */
float32_t f32VectorNormSq(float32_t pf32Vec[], uint8_t u8Len)
{
float32_t f32Norm = 0.0f;
uint8_t u8n = 0U;
VECTOR_ASSERT(pf32Vec!=NULL);
for(u8n = 0U; u8n < u8Len; u8n++)
{
f32NormSq += (pf32Vec[u8n] * pf32Vec[u8n]);
}
}
/* EOF */
Consumer of library:
/* file controller.c */
/* ... */
bool_t bControllerStep(void)
{
float32_t pf32MyVec[3] = { 0 };
float32_t f32MyNorm = 0.0f;
/* ... */
f32MyNorm = f32VectorNormSq(pf32MyVec, 3U);
/* ... */
}
/* EOF */
For option 1 the library function f32VectorNormSq() can be reasoned by the caller bControllerStep() to always execute successfully (return true),
because the array pf32MyVec is defined in the caller and pf32MyVec thus can't be NULL. Therefore the caller chooses to ignore the return value.
Above reasoning is likely to be the applicable for many uses of the library, resulting in callers
frequently ignoring return values for option 1. This could lead to a programmer being complacend in ignoring return values, even if they shouldn't, e.g. because a
zero division was detected by the library.
Opposed to this option 2 assumes the caller supplying valid pointers, documents this in the library /* #note...*/ and only uses a assert for NULL pointers to assist during development,
later to be disabled for deployment. In this option a Boolean return value being present highlights to the programmer that the library operation might fail for reasons
other than invalid pointers or incorrect other trivial inputs, e.g due to zero division and care should be taken before using the computed values,
avoiding the risk of complacency.
Therefore my question(s):
Is it situations as in the example shown compliant to MISRA C for a libary to neglect checking pointers or other trivial inputs?
Are there any additional conditions that have to be fullfilled, besides documenting the missing input checking in the source code, e.g. is a formal deviation needed?
Application background:
This is just an aerospace student with focus in control systems, trying to understand how things are done properly in the actual coding of control systems, by writing his own control algorithms as if they were running on the real thing i.e. by following standards like MISRA C.
Code written by me will NOT be going on a live system anytime soon, but for the purpose of your answers please consider this code as running on the actual system where a failure of the function is classified as catastrophic, .i.e. everybody dies.
I'm aware of the whole software and hardware engineering (SAE ARP4754, SAE ARP4761, DO-178C, ...) around the actual implementation process. This question is really just about the instructions executing on the hardware, not about the need for redudant & dissimilar hardware or requirements, reviews, testing, ...
EDIT:
The library in question is low in the code stack thus sanitizing code for inputs from the outside (sensors,...) can be expected to be present. I'm trying to avoid falling prey to Cargo cult programming by blindly following the rule "Always check all inputs".
Regarding Option 1 - how would you write the documentation to that function? Does this make sense:
bVectorNormSq
Description of what this function does here.
pf32Vec A pointer to an allocated array of [u8Len] that will-...
u8Len The size of the array [pf32Vec] in bytes.
...
Returns: true if successful, false in case pf32Vec was a null pointer.
It doesn't make sense. You already documented that pf32Vec must be a pointer to an allocated array so why would the usernot read that part, but read the part about return status? How are we even supposed to use this function?
bool result = bVectorNormSq(some_fishy_pointer, ...); // checks for null internally
if(result == false)
{
/* error: you passed a null pointer */
}
Why can't you instead write that very same code like this?
if(some_fishy_pointer == NULL)
{
/* handle the error instead of calling the function in the first place */
}
else
{
bVectorNormSq(some_fishy_pointer, ...); // does not check for null internally
}
It's the same amount of error checking, same amount of branches. Literally the only difference is the slower execution speed of the first version.
Also, your extra error checks add extra complexity which could in turn lead to extra bugs.
Potential bugs:
if( (pf32Vec = NULL) ||(pf32NormSq = NULL) )
or
if( (pf32Vec =! NULL) && (pf32NormSq != NULL) )
or (not just a potential bug):
bool_t ... bool bRet = false; ... return bRet;
Extra error checking is a good thing, but place it where it matters - sanitize data at the point where it gets assigned. Example:
const char* ptr = strstr(x,y);
if(ptr == NULL) // Correct! Check close to the location where the pointer is set
{}
...
some_function(ptr);
...
void some_function (const char* str)
{
if(str == NULL) // Not correct. This function has nothing to do with the strstr call.
}
I am currently writing a small game in C and feel like I can't get away from global variables.
For example I am storing the player position as a global variable because it's needed in other files. I have set myself some rules to keep the code clean.
Only use a global variable in the file it's defined in, if possible
Never directly change the value of a global from another file (reading from another file using extern is okay)
So for example graphics settings would be stored as file scope variables in graphics.c. If code in other files wants to change the graphics settings they would have to do so through a function in graphics.c like graphics_setFOV(float fov).
Do you think those rules are sufficient for avoiding global variable hell in the long term?
How bad are file scope variables?
Is it okay to read variables from other files using extern?
Typically, this kind of problem is handled by passing around a shared context:
graphics_api.h
#ifndef GRAPHICS_API
#define GRAPHICS_API
typedef void *HANDLE;
HANDLE init_graphics(void);
void destroy_graphics(HANDLE handle);
void use_graphics(HANDLE handle);
#endif
graphics.c
#include <stdio.h>
#include <stdlib.h>
#include "graphics_api.h"
typedef struct {
int width;
int height;
} CONTEXT;
HANDLE init_graphics(void) {
CONTEXT *result = malloc(sizeof(CONTEXT));
if (result) {
result->width = 640;
result->height = 480;
}
return (HANDLE) result;
}
void destroy_graphics(HANDLE handle) {
CONTEXT *context = (CONTEXT *) handle;
if (context) {
free(context);
}
}
void use_graphics(HANDLE handle) {
CONTEXT *context = (CONTEXT *) handle;
if (context) {
printf("width = %5d\n", context->width);
printf("height = %5d\n", context->height);
}
}
main.c
#include <stdio.h>
#include "graphics_api.h"
int main(void) {
HANDLE handle = init_graphics();
if (handle) {
use_graphics(handle);
destroy_graphics(handle);
}
return 0;
}
Output
width = 640
height = 480
Hiding the details of the context by using a void pointer prevents the user from changing the data contained within the memory to which it points.
How do you avoid using global variables in inherently stateful programs?
By passing arguments...
// state.h
/// state object:
struct state {
int some_value;
};
/// Initializes state
/// #return zero on success
int state_init(struct state *s);
/// Destroys state
/// #return zero on success
int state_fini(struct state *s);
/// Does some operation with state
/// #return zero on success
int state_set_value(struct state *s, int new_value);
/// Retrieves some operation from state
/// #return zero on success
int state_get_value(struct state *s, int *value);
// state.c
#include "state.h"
int state_init(struct state *s) {
s->some_value = -1;
return 0;
}
int state_fini(struct state *s) {
// add free() etc. if needed here
// call fini of other objects here
return 0;
}
int state_set_value(struct state *s, int value) {
if (value < 0) {
return -1; // ERROR - invalid argument
// you may return EINVAL here
}
s->some_value = value;
return 0; // success
}
int state_get_value(struct state *s, int *value) {
if (s->some_value < 0) { // value not set yet
return -1;
}
*value = s->some_value;
return 0;
}
// main.c
#include "state.h"
#include <stdlib.h>
#include <stdio.h>
int main() {
struct state state; // local variable
int err = state_init(&state);
if (err) abort();
int value;
err = state_get_value(&state, &value);
if (err != 0) {
printf("Getting value errored: %d\n", err);
}
err = state_set_value(&state, 50);
if (err) abort();
err = state_get_value(&state, &value);
if (err) abort();
printf("Current value is: %d\n", value);
err = state_fini(&state);
if (err) abort();
}
The only single case where global variables (preferably only a single pointer to some stack variable anyway) have to be used are signal handlers. The standard way would be to only increment a single global variable of type sig_atomic_t inside a signal handler and do nothing else - then execute all signal handling related logic from the normal flow in the rest of the code by checking the value of that variable. (On POSIX system) all other asynchronous communication from the kernel, like timer_create, that take sigevent structure, they can pass arguments to notified function by using members in union sigval.
Do you think those rules are sufficient for avoiding global variable hell in the long term?
Subjectively: no. I believe that a potentially uneducated programmer has too much freedom in creating global variables given the first rule. In complex programs I would use a hard rule: Do not use global variables. If finally after researching all other ways and all other possibilities have been exhausted and you have to use a global variables, make sure global variables leave the smallest possible memory footprint.
In simple short programs I wouldn't care much.
How bad are file scope variables?
This is opinion based - there are good cases where projects use many global variables. I believe that topic is exhausted in are global variables bad and numerous other internet resources.
Is it okay to read variables from other files using extern?
Yes, it's ok.
There are no "hard rules" and each project has it's own rules. I also recommend to read c2 wiki global variables are bad.
The first thing you have to ask yourself is: Just why did the programming world come to loath global variables? Obviously, as you noted, the way to model a global state is essentially a global (set of) variable(s). So what's the problem with that?
The Problem
All parts of the program have access to that state. The whole program becomes tightly coupled. Global variables violate the prime directive in programming, divide and conquer. Once all functions operate on the same data you can as well do away with the functions: They are no longer logical separations of concern but degrade to a notational convenience to avoid large files.
Write access is worse than read access: You'll have a hard time finding out just why on earth the state is unexpected at a certain point; the change can have happened anywhere. It is tempting to take shortcuts: "Ah, we can make the state change right here instead of passing a computation result back up three layers to the caller; that makes the code much smaller."
Even read access can be used to cheat and e.g. change behavior of some deep-down code depending on some global information: "Ah, we can skip rendering, there is no display yet!" A decision which should not be made in the rendering code but at top level. What if top level renders to a file!?
This creates both a debugging and a development/maintenance nightmare. If every piece of the code potentially relies on the presence and semantics of certain variables — and can change them! — it becomes exponentially harder to debug or change the program. The code agglomerating around the global data is like a cast, or perhaps a Boa Constrictor, which starts to immobilize and strangle your program.
Such programming can be avoided with (self-)discipline, but imagine a large project with many teams! It's much better to "physically" prevent access. Not coincidentally all programming languages after C, even if they are otherwise fundamentally different, come with improved modularization.
So what can we do?
The solution is indeed to pass parameters to functions, as KamilCuk said; but each function should only get the information they legitimately need. Of course it is best if the access is read-only and the result is a return value: Pure functions cannot change state at all and thus perfectly separate concerns.
But simply passing a pointer to the global state around does not cut the mustard: That's only a thinly veiled global variable.
Instead, the state should be separated into sub-states. Only top-level functions (which typically do not do much themselves but mostly delegate) have access to the overall state and hand sub-states to the functions they call. Third-tier functions get sub-sub states, etc. The corresponding implementation in C is a nested struct; pointers to the members — const whenever possible — are passed to functions which therefore cannot see, let alone alter, the rest of the global state. Separation of concerns is thus guaranteed.
so, I'm very new to C, coming from a Java/C# background and I can't quite wrap my head around it so far.
What I'm trying to do is program a microcontroller (Adafruit Feather running an atmega32u4 in this case) to pose as a USB-coupled controller for Nintendo Switch and run automated commands.
The project I'm trying to expand upon is using a struct array of commands like this:
typedef struct {
Buttons_t button;
uint16_t duration; // 1 equals 0.025s on ATmega32u4 => 1s = 40
} command;
static const command loop[] = {
// do stuff
{ NOTHING, 150 },
{ TRIGGERS, 15 }, { NOTHING, 150 },
{ TRIGGERS, 15 }, { NOTHING, 150 },
{ A, 5 }, { NOTHING, 250 }
};
Now initially this was all there was to it, the program would loop through the commands, send a button to the console and "hold" it for the defined period of time. When the program ran to the end of the array, it would simply reset the index and start anew.
Now I'm trying to send different commands to the console, based on a few easy if..else queries. Specifically, the program will start with a day, month and year variable (the date the Switch console is currently set to) and roll days forward individually to get to a set date in the future. To this end, I want to check at every 'step' if the date +1 day is valid as described in this tutorial and based on the result either roll one day, one day and one month or one day, one month and one year forward. Then I want it to end after a set amount of days.
I wrote several arrays of commands to represent the different steps needed for setting up the controller, moving to where it's supposed to loop, rolling a day, a month or a year like this:
static const command setupController[] = {
// Setup controller
...
};
static const command moveToLoop[] = {
// Go into date settings
...
};
static const command rollDay[] = {
//roll to next day
...
};
static const command rollMonth[] = {
//roll to next month
...
};
static const command rollYear[] = {
//roll to next year
...
};
And another array I want to copy those to like this:
#define COMMANDMAXSIZE 100
static command activeCommand[COMMANDMAXSIZE];
I know this is (extremely) wasteful of memory, but I'm definitely not good enough at C to come up with fancier, more conservative solutions yet.
Then I go into my program, which looks like this:
int main(void) {
SetupHardware(); //Irrelevant, because it is exactly like I downloaded it and it works even with the bumbling changes I've made
GlobalInterruptEnable(); //Ditto
RunOnce(setupController);
RunOnce(moveToLoop);
while (daysSkipped != stopDay)
{
if (datevalid((dayOfMonth + 1), month, year)) {
dayOfMonth++;
RunOnce(rollDay);
}
else if (datevalid(1, (month + 1), year)) {
dayOfMonth = 1;
month++;
RunOnce(rollMonth);
}
else if (datevalid(1, 1, (year + 1))) {
dayOfMonth = 1;
month = 1;
year++;
RunOnce(rollYear);
}
daysSkipped++;
}
}
and finally (I swear I'll be done soon), the start of RunOnce looks like this
void RunOnce(command stepsToRun[]) {
memcpy(activeCommand, stepsToRun, sizeof(activeCommand)); //set the setup commands to be active
activeBounds = sizeof(stepsToRun) / sizeof(stepsToRun[0]);
...
Later in the program, the task that translates commands into button presses for the console actually runs one fixed array, so I figured I'd just "mark" the commands to run as active, and only ever run the active array. Only, it doesn't work as expected:
The program runs, sets up the controller, moves to the date settings and indeed starts to roll a date, but then, regardless if the next day is valid or not, it rolls forward a month, then a year and then it gets stuck moving the simulated analog stick upwards and pressing A indefinitely.
I figure the problem lies in my memcpy to overwrite the active array with the steps I want to run next, but I can't think of a way to solve it. I tried writing a function that was supposed to overwrite the active array element by element using a for loop, but this way the controller wouldn't even set itself up correctly and effectively nothing happened. Usually with any kind of output capabilities I'd try to fit in prints at points of interest, but I have virtually no way of getting feedback on my microcontroller.
Any help would be greatly appreciated.
Ignoring that doing a hard copy of the data is incredibly slow and wasteful, it is also incorrect indeed.
memcpy(activeCommand, stepsToRun, sizeof(activeCommand));
Here you need to copy the size of the data you pass on, not the size of the target buffer! Right now you end up copying more data than you have, because all of these declarations static const command rollDay[] etc get a variable size depending on the number of items in the initializer list.
The quick & dirty fix to your immediate problem would be to pass along the size:
void RunOnce(size_t size, command stepsToRun[size])
{
memcpy(activeCommand, stepsToRun, size);
and then call this function with RunOnce(sizeof rollDay, rollDay); etc.
The activeBounds = sizeof(stepsToRun) / sizeof(stepsToRun[0]); part is also incorrect but not the immediate reason for the bug. See How to find the 'sizeof' (a pointer pointing to an array)? and What is array to pointer decay? etc.
When you pass array to function it decays to a pointer.
RunOnce(rollYear);
Thus
void RunOnce(command stepsToRun[]) {
memcpy(activeCommand, stepsToRun, sizeof(activeCommand)); //set the setup commands to be active
activeBounds = sizeof(stepsToRun) / sizeof(stepsToRun[0]);
}
sizeof(stepsToRun) doesn't yield the correct result as you expected, since it is now sizeof(pointer) in function.
You will have to pass the size of the array as an extra argument to RunOnce function.
I'm writting a C API for a embedded linux device. My problem is that the software must be portable ( run in diferent platforms ) without any further tweak. It would be good to not use compile time keys ( #ifdefs ).
The problem is that I need to export some capabilities from the hardware and APIs below mine. This should be done in run-time.
Say, I've a struct to define a XYZ position, but the range can be diferent,
the Z sometimes cannot be set. Besides that, it would be good to return a string with the reason.
struct position {
int x;
int y;
int z;
};
int go_to_position(struct position *next_position)
{
/* Do stuff */
return (0);
};
But suppose in some contexts I can change only x and y. In others, only y and z.
I wonder the best way to implement this, and if there is a know pattern.
I would do something like this:
#define PARAM_COUNT 3
enum { PARAM_X, PARAM_Y, PARAM_Y };
char*error_strings [PARAM_COUNT][PARAM_COUNT] = {
{"X don't work", Null , Null },
{Null, Null, "Z * Y cannot be larger than 10" },
{Null, "Z * Y cannot be larger than 10", Null },
};
char * check_position(struct position *position_to_check)
{
if( INTERNAL_CONSTRAINT(position_to_check->z, position_to_check->y)) {
return(error_strings[PARAM_Z][ PARAM_Y]);
}
if( INTERNAL_X_NOT_AVAILABLE() )
return(error_strings[PARAM_X][ PARAM_X]);
}
return (Null);
}
Is there a better way of doing this ? Any Ideas ?
Usually, you will have some additional API function to check the underlying capabilities.
For example, you may implement a function that will look like this :
QueryCapabilities( CAPABILITIES_XYZ, &capa );
Where capa is a structure containing various information about XZY ranges and availability (or whatever you need).
The higher level using this API will just have to check the capabilities, and adapt or fail depending on what is required.
Another point is what your API will do when given not-perfect parameters. One common approach is 'do your best', where your API will do what it can with the provided parameters. This can include ignoring unsupported parameters and capping out of range value (if max X is 10, 11 will be set to 10). You may make the function fail if a vital parameter is invalid. One other approach is to fail as soon as a parameter is not valid, because it indicates that the upper program is doing non-sense. You can also implement a 'do your best', but return a warning value when something is not OK.
I'm implementing a low pass filter in C wih the PortAudio library.
I record my microphone input with a script from PortAudio itself. There I added the following code:
float cutoff = 4000.0;
float filter(float cutofFreq){
float RC = 1.0/(cutofFreq * 2 * M_PI);
float dt = 1.0/SAMPLE_RATE;
float alpha = dt/(RC+dt);
return alpha;
}
float filteredArray[numSamples];
filteredArray[0] = data.recordedSamples[0];
for(i=1; i<numSamples; i++){
if(i%SAMPLE_RATE == 0){
cutoff = cutoff - 400;
}
data.recordedSamples[i] = data.recordedSamples[i-1] + (filter(cutoff)*(data.recordedSamples[i] - data.recordedSamples[i-1]));
}
When I run this script for 5 seconds it works. But when I try to run this for more then 5 seconds it fails. The application records everything, but crashes on playback. If I remove the filter, the application works.
Any advice?
The problem:
you are lowering the cutoff frequency by 400 Hz everytime i%SAMPLE_RATE == 0
never stop so you go below zero
this is not done once per second !!!
instead every time your for passes through second barrier in your data
that can occur more often then you think if you are not calling your calls in the right place
which is not seen in your code
you are filtering in wrong oorder
... a[i]=f(a[i],a[i-1]; i++;
that means you are filtering with already filtered a[i-1] value
What to do with it
check the code placement
it should be in some event like on packed done sompling
or in thread after some Sleep(...); (or inside timer)
change the cut off changing (handle edge cases)
reverse filter for direction
Something like this:
int i_done=0;
void on_some_timer()
{
cutoff-=400;
if (cutoff<1) cutoff=1; // here change 1 for limit frequency
if (numSamples!=i_done)
for (i=numSamples-1,i>=i_done;i--)
data.recordedSamples[i] = data.recordedSamples[i-1] + (filter(cutoff)*(data.recordedSamples[i] - data.recordedSamples[i-1]));
i_done=numSamples;
}
if your code is already OK (you did not post th whole thing so I can missing something)
then just add the if (cutoff<1) cutoff=1; after cutoff change