This is my Lab5 Algorithm Selection for my SPO600 class.

For this class I will be analyzing audio files, the performance of them, the compression, size, as well as scaling sound bites.

Yes after building vol.h and vol1.c it does have the same output every time and that output is -86 every time.

The runtime for the program is 0m0.038

The code itself:

int main() { // Allocate memory for large in and out arrays int16_t* in; int16_t* out; in = (int16_t*) calloc(SAMPLES, sizeof(int16_t)); out = (int16_t*) calloc(SAMPLES, sizeof(int16_t)); int x; int ttl; // Seed the pseudo-random number generator srand(-1); // ###################################### // This is the interesting part! // Scale the volume of all of the samples for (x = 0; x < SAMPLES; x++) { out[x] = scale_sample(in[x], 0.75); } // ###################################### // Sum up the data for (x = 0; x < SAMPLES; x++) { ttl = (ttl+out[x])%1000; } // Print the sum printf("Result: %d\n", ttl); return 0; }

No multiple runs do not run the same each time. The first time it ran it was in 0m0.038s, the next time it ran 0.035s, then it ran 0.036s, it randomly ran differently any time from 0.038s to 0.035s.

After we change our code to compensate for the pre-calculation of the lookup table of all possible samples values multiplied by the volume factors. After we compile and run the code with the changes we made it now consistently runs 0.032s for a total of roughly 0.004s or more faster run time, which does optimize the runtime of the program.

The code for this:

static inline int16_t scale_sample(int16_t sample, float volume_factor) { return (int16_t) (volume_factor * (float) sample); } int main() { // Allocate memory for large in and out arrays int16_t* in; int16_t* out; in = (int16_t*) calloc(SAMPLES, sizeof(int16_t)); out = (int16_t*) calloc(SAMPLES, sizeof(int16_t)); int x; int ttl; // Seed the pseudo-random number generator srand(-1); // Fill the array with random data for (x = 0; x < SAMPLES; x++) { in[x] = 0.75 * ((rand()%65536)-32768); } for (x = 0; x < SAMPLES; x++) { ttl = (ttl+out[x])%1000; } // Print the sum printf("Result: %d\n", ttl); return 0; }

Next we are to convert the volume factor 0.75 to a fix-point integer by multiplying by a binary number representing a fixed-point value “1”. For example, you could use 0b100000000 (= 256 in decimal) to represent 1.00. Shift the result to the right the required number of bits after the multiplication (>>8 if you’re using 256 as the multiplier).

The code is as such:

static inline int16_t scale_sample(int16_t sample, float volume_factor) { return (int16_t) (volume_factor * (float) sample); } int main() { // Allocate memory for large in and out arrays int16_t* in; int16_t* out; in = (int16_t*) calloc(SAMPLES, sizeof(int16_t)); out = (int16_t*) calloc(SAMPLES, sizeof(int16_t)); int x; int ttl; int scale = 256 * 0.75; // Seed the pseudo-random number generator srand(-1); // Fill the array with random data for (x = 0; x < SAMPLES; x++) { in[x] = (rand()%65536)-32768; } // Sum up the data for (x = 0; x < SAMPLES; x++) { ttl = (scale * (ttl+in[x] >> 8))%1000; } // Print the sum printf("Result: %d\n", ttl); return 0; }

The run time with this code is 0.030s which is slightly faster than both the first and second implementations. Of these implementations it seems that the third implementation is the fastest, slightly, followed by the second and then lastly the first.

Approach 1 has the program multiply each element by the volume, however it is slower than Approach 2 for the reason it precalculates all possible sample values multiplied by the volume factor. Approach 3 is the fastest as it multiplies the value straight into the variable.