Showing posts with label code. Show all posts
Showing posts with label code. Show all posts

Monday, 4 May 2015

Using Cubase LE as a debugger for my code



Using Cubase LE as a debugger for my code


While testing some code for some midi controllers i thought of using Cubase to better help me debug it.
* Black is received data, blue when negative bend, red when positive and light green/blue is no update on data ( does not reset automatically until told to).
Using Pitch bend in this case.smile emoticon

* Black is received data, Blue when negative bend, Red when positive and light green/blue is no update on data ( doesnt reset automatically until told to).
Using Pitch bend in this case.


Wednesday, 13 November 2013

Some insight into compilers ...

I had to share this link, due to its substance and context !
Craziest Compiler Output due to Undefined Behaviour

A lot of examples and links to detailed examples, causes and workarounds !
Every now and then, compilers still play a few tricks on us, due to our habits in coding !

Saturday, 9 November 2013

Cryptography from the vaults

Despite coming from the vaults of time, and some of the technologies mentioned being outdated, it still manages to be a good overall lecture on cryptography as a motivation for more hackers to get involved with it !


"HOPE took place on August 13-14, 1994 at Hotel Pennsylvania in New York City.
There have been quite a few articles in the national media recently about cryptography and privacy. Bob Stratton will attempt to provide an introduction to the terms and technology, how it affects the average citizen, and insights into the public policy debate currently raging in Washington and around the world. There will be a special emphasis on the relationship of cryptographic technology and emerging personal communications tools.

Also, a demonstration by Bernie S. and John Turbo of the AT&T 3600 Surety telephone device, the world's first Clipper Chip telephone encryption unit. Attendees will be invited to make telephone calls between two AT&T 3600's and a loudspeaker will enable all present to actually hear the encrypted audio. An actual Clipper Chip will be given away as a door prize with the opportunity to smash it with a hammer in front of all.

Also featuring Eric Hughes and Matt Blaze."

They also mention a classic book "The code breakers" as a good reading !

Monday, 28 October 2013

ADSR Exercises...

The exponential attack curves available will have these different options, in the final version !

I had to try to rethink the ADSR block of my project, as there are some variations that i want to include, and that make it different from other methods more popular often used in synths. Plus, what im building is not your average synth either, so here are some of the results of my tests ! Still need to test it as far as performance goes to be able to decide if ill go with an exponential attack( i am quite confident it can be calculated between interrupts, so as not to weigh too much on the interrupt load, itself !
I tried to make it as readable as possible; There are a lot of short cuts available to make it more efficient and optimize it. Which shall be taken into consideration in the final code . This one was wrote in tutorial style; several of the calculations can be shortened , optimized, for better performance. But then, it wouldn't have been as readable as this, i guess !
So, here it is for now !.


//*    Synth Building blocks 
//*    ATTACK-DECAY-SUSTAIN-RELEASE for Wavetable-based Generator #0.1
//*    Check section "Synth building blocks related" @
//*    http://dubworks.blogspot.co.uk/p/my-self-documented-tutorials.html
//*    Result of my experiences into the ADSR part of my project. Keep in mind that i decided to re-trhink it, 
//*    as what im working on is not your usual synth, but something else slightly(?!) different.
//*    This code was wrote for readability more than anything else ! There are a lot of short cuts available
//*    to make it more efficient and optimize it. Which shall be taken into consideration in the final code 

#define xinc (1.00/param.attack) // Allows an exponential attack
#define sigl 4095 // Despite being a constant here, it should be replaced by the wavetable equivalent
//
uint32_t phaseinc,output;
//
//  Declare the struct for our ADSR
struct ADSR {
  uint16_t period;  // total of the whole period
  uint16_t attack;
  uint16_t decay;
  uint16_t sustain;
  uint16_t rlease;
  float x;  // increment for period, to accum xinc by addition
};
struct ADSR param; // initialize the structure, so it is in scope !
//
//boolean led = false; 
//
void update (){
  if(phaseinc <= param.period){
    //
    if(phaseinc < param.attack){
      float y;
      y= pow(param.x , 0.50);  // Expon. attack-generator. This is where my latest tests been focusing on
      output= sigl * y;  //Ramp up can be achieved by just multiplying it by param.x as well, though 
      //  it would be a waste of computing power, as there are easier and "cheaper" ways to do it !

      //      Serial.print ("attack ");
      //      Serial.println (attack);
      //      Serial.print ("Output ");
      //      Serial.println (output);
    }
    else if(phaseinc >= param.attack && phaseinc <(param.attack + param.decay)){
      //
      output = sigl-((phaseinc - param.attack)*(512.0/param.decay)); //512= 4096 * 1/8
      //      Serial.println ("decay");
      //      Serial.println (param.decay);
      //      Serial.print ("Output ");
      //      Serial.println (output);
    }
    else if(phaseinc >=(param.attack + param.decay) && phaseinc <(param.attack + param.decay + param.sustain)){
      //
      //      Serial.print ("sustain");
      //      Serial.println (param.sustain);
      output = sigl *(7/8.00);
      //      Serial.print ("Output ");
      //      Serial.println (output);
    }
    else if(phaseinc >(param.attack + param.decay + param.sustain) && phaseinc < param.period){
      //
      //      Serial.print ("rlease");
      //      Serial.println (param.rlease);
      output=(param.rlease-(phaseinc-(param.attack+param.decay+param.sustain)))*((sigl*(7/8.00))/param.rlease);
      //      Serial.print ("Output ");
      //      Serial.println (output);  
    }
  }
}
//
void ADSR_calculation()
{ 
  //  There are more exciting ways to calculate division and remainders.
  //  We wrap-up with  a "modulo-like" operator for
  //  the last variable sustain- a "greatest-integer function" of sorts .
  //  This way we can go from decay to release directly. Todo list is to loop inside the sustain
  //  For now im planning using 3 sec/1 as MAXIMUM of the whole period for ADSR.
  uint16_t b    = param.period >> 1;  // These operations help us achieve a cheap aproximation
  param.attack  = param.period >> 2; 
  param.decay   = b/3;
  param.rlease  = param.period >> 2;
  param.sustain = param.period -(param.attack + param.rlease + param.decay); 
  // same as 
  // param.sustain = param.period %(param.attack + param.rlease + param.decay);
  /*if(Serial){
   Serial.print ("attack ");
   Serial.println (param.attack);
   Serial.print ("decay ");
   Serial.println (param.decay);
   Serial.print ("sustain ");
   Serial.println (param.sustain);
   Serial.print ("rlease ");
   Serial.println (param.rlease);
   }*/
}
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  //variable for the period; To be analogous to the analog read/s and should be declared with an initial 
  //value(21504?!), before the buffering of the initial values , at the time of wavetable generation
  param.period=128;  //this value should be the sum of all ADSR values, so we can have variable-lenght 
  //  on each of the individual parameters of the ADSR !It is already in the tODO list !
  //  But for now, ill leave it as it is: weighed proportionally !
  //
  ADSR_calculation();
}

void loop() {

//  if(Serial){
//    Serial.print ("phaseinc ");
//    Serial.println (phaseinc);
//  }
  //
  update();  
  //This can be done between interrupts, as there is some calculations involved.

  phaseinc++;
  //Serial.println(phaseinc);
  if( phaseinc >= param.period ){
    phaseinc= phaseinc - param.period;
    ADSR_calculation();
  }
  param.x += xinc;
  if (param.x >= 1){
    param.x = 0;
  }
  Serial.println (output);
}


Arduino Decimal to Roman numerals converter- The code for Olimex WPC #30

Ok, here is the story :
Friday i saw the "Olimex WPC #30 Problem" just posted and decide to participate...MORE: I was going to try to be the first one to apply a working project, regardless of the "cost".
So i rushed, cheated, took no notice of programming "rules", and VOILA !
Also, as i rarely(?!) see an "Arduino Language" entry ( if you can call it that) , i decided it was what id be applying with ( and because i had nothing else more to code with, at the time :) ).
Added my good mood to the vibes, and this is what came out !
Will only work up to 9999 numbers... If you do a calendar with it, they will probably think it is the end of the world in the year 9999, due to my laziness !!
It was the fastest, laziest way i could find at the time !
* Dont take this code too serious...

**See the results here !https://github.com/OLIMEX/WPC/tree/master/ISSUE-30


// Enjoy the random names for variables and function at moments. 
// and learn how to write down the year that Olimex was founded in Roman numerals
// For completion, i give you the foundation of their fraction system: A twelfth !
// DISCLAIMER : Any similarities with attempt at comedy is pure coincidence !
//        CHANGE THIS to test other numbers ( up tp 9999
//         | | | | |    
//         V V V V V
char plaintext[]="1991"; // Why a char[] array? More user friendly with both c and c++
// and because i can !! :)

int tocipher[sizeof(plaintext)];
int ciphered[sizeof(tocipher)];

boolean stringComplete = false;  // whether the string is complete
boolean done = false; // no relationship between the name and function ! ;)

void setup() {
  // DO NOT put your code here to run once ?!?!
  Serial.begin(9600);
  Serial.println("Roman Numeral History Lesson with Olimex Pt.1");
}

void loop() 
{ 
  while(Serial){
    if(stringComplete == true)  // How long is a piece of string ?!
    {
      calculate();
      Serial.println("string complete");
      fractions();
      //
    }
    if(stringComplete == false){
      Serial.println("string NOT complete");
      // put your debug code here, to find out where you was going wrong: 
      uint8_t sizeofarray = sizeof(plaintext);
      uint8_t i;
      //
      for(i=0;i<=sizeofarray;i++)
      {
        uint16_t retrieved;
        retrieved=plaintext[i];
        leap(retrieved,i);
        Serial.println(retrieved);

        if(retrieved==0){
          Serial.print(i);
          Serial.println(" characters in the string processed.END OF STRING "); // Thats how long a string is :)
          Serial.println("null CHARACTER");
          stringComplete = true; 
          // The use of goto's is highly frowned upon...
          // ...but can be quite handy as well !
          goto bailout; 
        }
      }
bailout: // " Bloody bankers taken all !"
      delay(1); // As the tradition says:" Rome and Pavia weren't made in one day!
    }  
    while(done==true){
      // Allowing time for Nero to play with fire !
    }
  }
}

int leap(int in,int il){
// tocipher[il]=in; would have been enough
  switch (in) {
  case '0':  
    //
    Serial.println("tocipher- 0 ");
    tocipher[il]=0;
    break;
  case '1':
    Serial.println("tocipher- 1 ");
    tocipher[il]=1;  
    //
    break;
  case '2': 
    Serial.println("tocipher- 2 ");
    tocipher[il]=2;  
    //
    break;
  case '3': 
    Serial.println("tocipher- 3 ");
    tocipher[il]=3;  
    //
    break;
  case '4':
    Serial.println("tocipher- 4 ");
    tocipher[il]=4;  
    //
    break;
  case '5': 
    Serial.println("tocipher- 5 ");
    tocipher[il]=5;  
    //
    break;
  case '6':
    Serial.println("tocipher- 6 ");
    tocipher[il]=6;  
    //
    break;
  case '7':
    Serial.println("tocipher- 7 "); 
    tocipher[il]=7;  
    //
    break;
  case '8':
    Serial.println("tocipher- 8 ");
    tocipher[il]=8;  
    //
    break;
  case '9': 
    Serial.println("tocipher- 9 ");
    tocipher[il]=9;  
    //
    break;
    //
  default:
    //
    break;
    //
  }
}

void calculate(){
  uint16_t sizeofarray = sizeof(tocipher);
  int i;
  //
  for(i=0;i<=sizeofarray;i++)
  {
    int retrieved;
    retrieved=tocipher[i];
    bigjump(retrieved,i);
    //
  }
}

int bigjump(int coming, int il){

  switch (il) { 
  case 0:
    int k;
    Serial.print("Year Olimex was founded in Roman numerals- ");
    for(k=0;k<coming;k++){
      Serial.print("M");
    }
    break;

  case 1:
    if(coming==9){
      Serial.print("CM");
    }
    if (coming==8){
      Serial.print("DCCC");
    }
    if (coming==7){
      Serial.print("DCC");
    }
    if (coming==6){
      Serial.print("DC");
    }
    if (coming==5){
      Serial.print("D");
    }
    if (coming==4){
      Serial.print("CD");
    }
    if (coming==3){
      Serial.print("CCC");
    }
    if (coming==2){
      Serial.print("CC");
    }
    if (coming==1){
      Serial.print("C");
    }
    break;

  case 2:
    if(coming==9){
      Serial.print("XC");
    }
    else if (coming==8){
      Serial.print("LXXX");
    }
    else if (coming==7){
      Serial.print("LXX");
    }
    else if (coming==6){
      Serial.print("LX");
    }
    else if (coming==5){
      Serial.print("L");
    }
    else if (coming==4){
      Serial.print("XL");
    }
    else if (coming==3){
      Serial.print("XXX");
    }
    else if (coming==2){
      Serial.print("XX");
    }
    else if (coming==1){
      Serial.print("X");
    }
    break;

  case 3:
    if(coming==9){
      Serial.print("IX");
    }
    else if (coming==8){
      Serial.print("VIII");
    }
    else if (coming==7){
      Serial.print("VII");
    }
    else if (coming==6){
      Serial.print("VI");
    }
    else if (coming==5){
      Serial.print("V");
    }
    else if (coming==4){
      Serial.print("IV");
    }
    else if (coming==3){
      Serial.print("III");
    }
    else if (coming==2){
      Serial.print("II");
    }
    else if (coming==1){
      Serial.print("I");
    }
    done=true;
    break;

  case 4:
    Serial.println("");
    break;  

  default:
    break;
  }
}


void fractions(){
  // Any similarites with attempt at comedy is pure coincidence !
  uint16_t sizeofarray = sizeof(tocipher);
  int i;
  //
  for(i=0;i<=sizeofarray;i++)
  {
    int retrieved;
    int accum;
    retrieved=tocipher[i];
    int result=0;
    switch (i) {
    case 0:  
      //
      accum=(retrieved*1000);
      Serial.print("result thou ");
      Serial.println(accum);
      break;
    case 1:
      accum+=(retrieved*100); 
      Serial.print("result with hundr");
      Serial.println(accum); 
      //
      break;
    case 2: 
      accum+=(retrieved*10); 
      Serial.print("result with decim ");
      Serial.println(accum); 
      //
      break;
    case 3: 
      accum+=retrieved; 
      Serial.print("total result ");
      Serial.println(accum);
      //
      break;

    case 4:
      Serial.print("Proverbial 1/12 (twelfth) Roman fracction ");
      Serial.print((float)(accum/12));
      break;

    default:
      break;
      //
    } 
  }
}
















Wednesday, 23 October 2013

Some exercises with the "Caesar cipher" Pt 2.

Plaintext    |a |b |c  |d |e |f  |g |h |i   |j | k | l  | m| n| o | p | q  | r  | s | t  | u | v | w | x | y | z |
P-Number  |0 |1 |2 | 3 |4 |5 |6 |7 |8 |9 |10|11|12|13|14|15 |16 |17|18|19|20|21|22 |23|24|25|
Ciphertext |d |e | f | g |h |i  |j  |k |l |m | n | o | p | q | r  | s| t  | u | v | w | x | y | z  | a | b  | c |

In the Caesar cipher, the modulus operator was used to achieve a fast way of computing the result.
The use of an array from 0 to 25 is inherent to the discrete implementation methods widely used. Look-up tables also get this particularity many a times !
If it is not obvious why, wait until one of the next posts on the subject. Other examples will surely make obvious why .
Let's remember  what was said in a previous post :

// Caesar cipher ==> C = (P+s) Mod (Number_of_Characters)
// Number_of_Characters also known as Keyspace = 26 (0 to 25)
// P = numerical equivalent of character plaintext
// C = Numerical equivalent of cipher text character
// s = number of shifts,adds (n_shift)
// Ke = s = 3 ==> (P+s) mod (Number_of_Characters)
// Kd = -s = -3 ==> (C -s)mod (Number_of_Characters) (reverse operation)

From this, we can then adapt this idea into the way the ascii numerical code uses to represent printable characters.

// Keyspace = 96 ( Nchars; )
// P = retrieved
// s =  n_shift
// [ from "ascii'" character number 32-decimal; 040-OCT; 20-HEX; 00100000-BIN ==> "SPACE" 
// to "ascii'" character number 126 decimal; 176-OCT; 7E-HEX; 01111110-BIN; ==> "~" Equivalence sign - tilde

The way i found was to first subtract  an ascii_offset (retrieved -=32;) compute the algorithm ( uint16_t c =(retrieved + n_shift)% Nchars; ) and then re-add the ascii_offset (retrieved +=32;).

C = (P+s) Mod ( Keyspace )

I should probably note the fact that it should not be confused with the remainder.
Let us see why...

If in C = A modulus B ,  A=13 and B=5 , then C=3 ;
If    C = A remainder B, then it is also C=3.

BUT (and there are always but's) what if we give A=13 and B= -5 ?!
Then, we would get A Modulus B ==> C= -2; In turn, A Remainder B ==> C=3 !!

Oh, yeah !! The art of the Modulus operator in itself  ( specially with only the use of a hand calculator), and its relationship with cryptography, is an art in itself , and can easy allow for a series of posts elaborating on it !
As an example, check the table below (created with Gnumeric) .



Code here
https://docs.google.com/document/d/1CbK-v1OaQIhbr0ao5EY8CrGZ71M9-t4cav4bK4JBwo0/edit?usp=sharing

Saturday, 12 October 2013

options to attack envelope


Ill keep it simple and share the graphic of the differences and options. Ramp legend is a linear ramp-up attack.
Following the example of period 128, we'd get : attack=32; decay=22; sustain=42; rlease=32.
the picture below is related to the ATTACK stage only.

More soon to come !



void adsr_calculation()
{
  uint16_t b = period >> 1;  // These operations help us achieve a cheap aproximation
  uint16_t a = b >> 3;  // of division by 3 (?!) with a loss of bits/precision, but weighed 
  //  enough for what we need, regarding the fact we wrap-up with  a modulo operator for
  //   the last variable sustain- a "greatest-integer function" of sorts .
 
 /*
 By combining the terms in an obvious manner we can reduce the number of operations:
   
   a = (period >> 2) + (period >> 4) 
   b += (b >> 4)
   b += (b >> 8)
   b += (b >> 16)
   There are more exciting ways to calculate division and remainders.
       b * 3 = shift left 1 bit and then add b
*/

  attack  = period >> 2; 
  decay   = (a <<1)+(a>>1)+(a>>2);
  rlease  = period >> 2;
  sustain = period -(attack + rlease + decay);
  // roughly the same as 
  // sustain = period %(attack + rlease + decay);
  led =!led;    //toggle led
  /* Serial.println ("a");
   Serial.println (a);
   Serial.println ("b");
   Serial.println (b);
   Serial.println ("attack");
   Serial.println (attack);
   Serial.println ("decay");
   Serial.println (decay);
   Serial.println ("sustain");
   Serial.println (sustain);
   Serial.println ("rlease");
   Serial.println (rlease);
   */
}

Regarding REAL division by three



// Crazy as this might sound, but the method below indeed does divide by 3. 
// All it needs for doing so is a single 64 bit multiplication and a shift 
// (multiplications might be 3 to 4 times faster than divisions 
// on your CPU). In a 64 bit application this code will be a lot faster than 
// in a 32 bit application (in a 32 bit application multiplying two 64 bit 
// numbers take 3 multiplications and 3 additions on 32 bit values) 
// - however, it might be still faster than a division on a 32 bit machine.
// It only works for constant numbers. Why ?!
// You always need to know the magic number (here 0xaaaaaaab, 
// 0b1010 1010 1010 1010 1010 1010 1010 1011 ; 2,863,311,531 decimal) 
// and the correct operations after the multiplication (shifts and/or additions 
// in most cases)and both is different depending on the number you want to divide// by (and to calculate both take too much CPU time, on the fly (that would be 
// slower than  hardware division). However, it's easy for a compiler to 
// calculate these during compile time 
static inline uint32_t div3 (
uint32_t bdivided
) {
  return (uint32_t)(((uint64_t)0xaaaaaaabULL * bdivided) >> 33);
}
void setup() {
  // put your setup code here, to run once:
  Serial.begin (115200);
}

void loop() {
  // put your main code here, to run repeatedly: 
  uint32_t test=1000;
  uint32_t avar=div3(test);
  Serial.println(avar);
  delay(500);
}

Thursday, 3 October 2013

Blindspots in code programming

Not news that we all got stuck with silly typos or "mistakes" while debugging some code: Big endianess? N-1 Ring-Buffer ?! Wrong datatype conversion/interaction?! hmmm...
As "developing some blindspots" its something that affects us all from time to time, when writing code, i decided to share some nice examples usually referenced as main examples( though, tbh, there are journalistic column entitled "IT Hiccups of the week", which speaks for itself :).

1- The Ariane 5 rocket, who got confused and got lost

On 4 June 1996 the maiden flight of the Ariane 5 launch ended in a failure, about 40 seconds after initiation of the flight sequence. At an altitude of about 3700 m, the launcher veered off its flight path, broke up and exploded. The failure was caused by "complete loss of guidance and attitude information" 30 seconds after liftoff.
A program segment for converting a floating-point-number to a signed 16-bit integer was executed with an input data value outside the range representable by a signed 16-bit integer. This run time error (out of range, overflow), which arose in both the main and backup computers at about the same time, was detected and both computers shut themselves down. This resulted in the total loss of altitude control. The Ariane 5 turned uncontrollably and aerodynamic forces broke it apart. This was detected by an on-board monitor which ignited the explosive charges to destroy the vehicle in the air. 

* Funny enough, the result of this conversion was no longer needed after, lift off.

reference: http://en.wikipedia.org/wiki/Ariane_5
http://www.rvs.uni-bielefeld.de/publications/Incidents/DOCS/Research/Rvs/Misc/Additional/Reports/ariane.html



2- The Patriot Missile who was late...

On February 25, 1991, during the Gulf War, an American Patriot Missile battery in Dharan, Saudi Arabia, failed to track and intercept an incoming Iraqi Scud missile. The Scud struck an American Army barracks, killing 28 soldiers and injuring around 100 other people. A report of the General Accounting office, GAO/IMTEC-92-26, entitled Patriot Missile Defense: Software Problem Led to System Failure at Dhahran, Saudi Arabia reported on the cause of the failure.

The bug occurs in the calculation of the next location of the incoming target by the range gate. The prediction is calculated based on the target’s velocity and the time of the last radar detection.
Velocity is stored as a whole number and a decimal, and time is a continuous integer or whole number (i.e. the longer the system has been running, the larger the value) measured in tenths of a second.
The algorithm used to predict the next air space to scan by the radar requires that both velocity and time be expressed as real numbers. However, the Patriot’s computer only has 24 bit fixed-point registers. Because time was measured as the number of tenth-seconds, the value 1/10, which has a non-terminating binary expansion, was chopped at 24 bits after the radix point.5 The error in precision grows as the time value increases, and the inaccuracy resulting from this is directly proportional to the target’s velocity.
When the Patriot system was first designed, the primary targets were Soviet aircraft and cruise missiles travelling at speeds around MACH 2, and only operating at a few hours at a time. However, in Operation Desert Storm, they were deployed as static defences (operating continuously), tracking and intercepting Scud missiles travelling at speeds of approximately MACH 5

"It turns out that the cause was an inaccurate calculation of the time since boot due to computer arithmetic errors.
Specifically, the time in tenths of second as measured by the system's internal clock was multiplied by 1/10 to produce the time in seconds. This calculation was performed using a 24-bit fixed-point register. In particular, the value 1/10, which has a non-terminating binary expansion, was chopped at 24 -bits after the radix point.
The small chopping error, when multiplied by the large number giving the time in tenths of a second, led to a significant error. 
Indeed, the Patriot battery had been up around 100 hours, and an easy calculation shows that the resulting time error due to the magnified chopping error was about 0.34 seconds. (The number 1/10 equals 1/24+1/25+1/28+1/29+1/212+1/213+.... In other words, the binary expansion of 1/10 is 0.0001100110011001100110011001100.... Now the 24 bit register in the Patriot stored instead 0.00011001100110011001100 introducing an error of 0.0000000000000000000000011001100... binary, or about 0.000000095 decimal. Multiplying by the number of tenths of a second in 100 hours gives 0.000000095×100×60×60×10=0.34.) 
A Scud travels at about 1,676 meters per second, and so travels more than half a kilometer in this time. This was far enough that the incoming Scud was outside the "range gate" that the Patriot tracked.
Ironically, the fact that the bad time calculation had been improved in some parts of the code, but not all, contributed to the problem, since it meant that the inaccuracies did not cancel."

Reference- "Failure at Dhahran " http://en.wikipedia.org/wiki/MIM-104_Patriot

3- Therac-25 : At a costly price ...

It is hard to reference this one, as it was the most costly, specially as the victims thought that the same device would be the one that would help improve their health, instead of the end result!