Algorithm Selection/ Sampling using C language

I will begin with a C language program given to me by Chris Tyler (https://wiki.cdot.senecacollege.ca/wiki/User:Chris_Tyler)

The file will be named “vol.c”

#include "stdlib.h"
#include "stdio.h"
#include "stdint.h"
#include "vol.h"

// Function to scale a sound sample using a volume_factor
// in the range of 0.00 to 1.00.
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] = (rand()%65536)-32768;
        }

        // ######################################
        // 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;

}

This program will use a file called “vol.h”

#define SAMPLES 500000

The file “vol.h” only contains the sample size that the program will be sampling. 500000 will be the default sample size.

I will be using a Makefile program to compile the programs, called “Makefile”

# list all binaries in this next line
BINARIES = vol1
CCOPTS = -g -O3

all: ${BINARIES}

vol0: vol0.c vol0.h
gcc ${CCOPTS} vol0.c -o vol0

vol1: vol1.c vol.h
gcc ${CCOPTS} vol1.c -o vol1

vol2: vol2.c vol2.h
gcc ${CCOPTS} vol2.c -o vol2

vol3: vol3.c vol3.h
gcc ${COOPTS} vol3.c -o vol3

vol4: vol4.c vol4.h
gcc ${COOPTS} vol4.c -o vol4

# target to test all binaries
gdb1: vol1
gdb vol1

clean:
rm ${BINARIES} || true

Background:

Sampling is used to change an analog data into a digital data. The analog data can be voice or sound. Standards were made to ensure the minimum and maximum amount of sound is heard. I went and did a search on the Internet to find the default sampling rate and got this webpage from the first result on www.google.ca (https://manual.audacityteam.org/man/sample_rates.html) The website describes audio samples as bandwidth and it is measured in Hertz(Hz). The website also explains the Nyquist Frequency that has a lower sampling limit of 20000Hz and an upper sampling limit of 22050Hz. (This is only half of the requirement as the average human has two ears) The sampling will have to be double the original sampling value to get the final sampling value. A lower limit of 40000Hz and an upper or maximum limit of 44100Hz.  (More commonly known as 44.1KHz of sampling)

The Sampling will have to also consider the loudness or scaling of the sample. 0 being silence and 1 being maximum loudness.

The sampling tests will be performed on an Aarch64 Linux OS, Cortex-A57 octa-core CPU system.

The programs will be compiled using the glibc program free to install on any Linux OS system.

Tests

Now to start with the tests.

I would use a command:

make vol1

This is because the glibc program was installed on the system and the Makefile has the required code to compile the C language program into an new file called ¨vol1¨

Alternatively, I can track the time it takes to compile the program using the built-in timer that Linux has.

time make vol1

The time command returns three different values in Linux:

Real, User and Sys.

Real time is the time the CPU takes to perform a task. User time is the time to run a task. Sys time is the time it takes the system to perform or call the task and execute it. Sys time will change depending on the amount of users actively performing tasks.

First Test

A sampling size of 500000 set in the vol.h file and I complied it.

Using this command:

time make vol1

or

time gcc -g -O3 vol1.c -o vol1

Result: -86

Real time: 0.115s

User time: 0.103s

Sys time: 0.013s

The real time is CPU time used. The compiling time takes 115 milliseconds to run on the CPU. The user time is the time used for running the code as a process. The compiler takes 103 milliseconds to compile. The Sys time is the time it took to request the system to perform the command. This program waits 13 milliseconds before it can use the CPU and System resources. The result does not change from -86.  (The results will be brief from now on.)

Now to run the program using:

./vol1

or to time the command:

time ./vol1
The first time to sampling:

Real time: 0.036s
User time: 0.035s

Sys time: 0.000s

Second time to sampling:

Real time: 0.036s

User time: 0.027s

Sys time: 0.009s

Third time to sampling:

Real time: 0.036s

User time: 0.036s

Sys time: 0.000s

File size: 70808 bits
500000 sample size estimated average time:

Real time: 0.036s

User time: 0.035s

Sys time: 0.000s

Comment:

Notice that during the second time sampling had a change in Sys time as another user was probably also using the system’s resources. The Real and User times were relatively the same in those sampling tests.

Second Test

This test will be changing the size of sampling to 5000000.

I copied both vol1.c and vol.h to vol2.c and vol2.h.

I then changed the sampling size in the vol.h file from 500000 to 5000000.

I used these commands:

cp vol1.c vol2.c
cp vol.h vol2.h
vi vol2.h

I compiled the program using the Makefile and ran the program as mentioned during the First Test.

Compiling time:

Real time: 0.122s

User time: 0.091s

Sys time: 0.027s

The first time sampling:

Result: 244

Real time: 0.258s

User time: 0.238

Sys time: 0.020s

The second time sampling:

Real time: 0.260s

User time: 0.230s

Sys time: 0.030s

The third time sampling:

Real time: 0.258s

User time: 0.238s

Sys time: 0.020s

The fourth time sampling:

Real time: 0.260s

User time: 0.250s

Sys time: 0.010s

File Size: 74520 bits
5000000 sample size estimated average time:

Real time: 0.258s

User time: 0.238s

Sys time: 0.020s

Comment:

Doing four tests with the changed sampling size causes the system to take more time each varying about 10 milliseconds. Currently this increases the time spent to compile and run the sampling program compared to the First Test. The result still remains 244 through each sampling test.

Third Test

I will now change the sampling size to 50000.

Repeating the steps from the Second Test to make a copy of the sampling program from vol1.c named vol0.c and change the sampling size in the new copy of vol0.h to 50000.

I compiled and ran the program like before.

Result: -838
Compile time:

Real time: 0.119s

User time: 0.075s

Sys time: 0.044s

The first time sampling:

Real time: 0.005s

User time: 0.004s

Sys time: 0.000s

The second time sampling:

Real time: 0.028s

User time: 0.027s

Sys time: 0.001s

Comment:

Changing the sampling size to a lower amount does lower the time to compile and run the sampling program. The result remains -838 through each sampling test.

Fourth Test

This test will change the sampling program to use a lookup table instead of a multiplicative factor.

Repeat the steps to copy and rename the files: vol1.c and vol.h file to vol4.c and vol4.h.

Three new lines of code will be added:

int16_t lookuptable[65536];
lookuptable[x] = (int16_t)(x * 0.75);
out[x] = lookuptable[(u_int16_t)in[x]];
  1. int16_t lookuptable[65536]; code will be creating an array table for values to be compared to when a given input is received from sampling.
  2. lookuptable[x] = (int16_t)(x * 0.75); code will take each value in the lookup table and multiply the input with 0.75 scale/ loudness.
  3. out[x] = lookuptable[(u_int16_t)in[x]; will output the matching output from the given input of sampling.

The code for vol4.c will look like this:

#include "stdlib.h"
#include "stdio.h"
#include "stdint.h"
#include "vol.h"

// Function to scale a sound sample using a volume_factor
// in the range of 0.00 to 1.00.
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;
//Add a lookup table array with 65536 possible values of 16-bits
int16_t lookuptable[65536];
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] = (rand()%65536)-32768;
}

//Lookup table for scaled samples
for(int x = 0; x < 65536; x++){
//Each value in the lookup table is muliplied by a factor of 0.75 
lookuptable[x] = (int16_t)(x * 0.75);
}

// ######################################
// This is the interesting part!
// Scale the volume of all of the samples
for (x = 9; x < SAMPLES; x++) {
//out[x] = scale_sample(in[x], 0.75);
//Make the output lookup a scaled value for the given input
out[x] = lookuptable[(u_int16_t)in[x]];
}
// ######################################

// 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;

}

I will change the sampling size to the value of 5000000 in the vol5.h file like in the other tests.

I will compile and run the program as before using the make and time commands.

Result: 907
Compile time:

Real time: 0.094s

User time: 0.062s

Sys time: 0.032s

The first time sampling:

Real time: 0.329s

User time: 0.299s

Sys time: 0.030s

The second time sampling:

Real time: 0.326s

User time: 0.306s

Sys time: 0.020s

The third time sampling:

Real time: 0.375s

User time: 0.355s

Sys time: 0.020s

The fourth time sampling:

Real time: 0.326s

User time: 0.306s

Sys time: 0.020s

Comment:

Like any other sampling tests the results remain 907

I made a mistake in the vol4.c program. In this section:

// ######################################
// This is the interesting part!
// Scale the volume of all of the samples
for (x = 9; x < SAMPLES; x++) {
//out[x] = scale_sample(in[x], 0.75);
//Make the output lookup a scaled value for the given input
out[x] = lookuptable[(u_int16_t)in[x]];
}
// ######################################

The x = 9 should have been  x = 0.

Now I will redo the Fourth Test with the changed  value.

Recompiling changes the results a bit.

Result: 760
The file size: 70766 bits
The compile time:

Real time: 0.099s

User time: 0.080s

Sys time: 0.015s

The first time sampling:

Real time: 0.326s

User time: 0.316s

Sys time: 0.010s

The second time sampling:

Real time: 0.327s

User time: 0.307s

Sys time: 0.020s

The third time sampling:

Real time: 0.329s

User time: 0.328s

Sys time: 0.000s

The fourth time sampling:

Real time: 0.332s

User time: 0.312s

Sys time: 0.020s

Comment:

The new value did not change the slow time of compiling and running the sampling program. This is probably because the lookup table is being constantly check for a new sample value slowing the CPU and system. The result still remains 760 for each sampling test.

The Fifth Test

This test will change the volume factor to a fixed-point value.

I will start by copying and changing the vol1.c and vol.h file again to vol5.c and vol5.h.

I will change the sampling value in vol5.h to 5000000 like the previous tests.

I will add new code to change the volume factor using this code:

int16_t volume_factor = 0.75 * 256;

The vol5.c file should look like this:

#include "stdlib.h"
#include "stdio.h"
#include "stdint.h"
#include "vol.h"

// Function to scale a sound sample using a volume_factor
// in the range of 0.00 to 1.00.
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));
//Add a fixed-point integer multiply by a binary number
int16_t volume_factor = 0.75 * 256;

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] = (rand()%65536)-32768;
}

// ######################################
// 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;

}

I will compile and run the program like the previous tests.

The File Size: 70808 bits
The compile time:

Real time: 0.093s

User time: 0.049s

Sys time: 0.044s

The first time sampling:

Real time: 0.035s

User time: 0.035s

Sys time: 0.000s

The second time sampling:

Real time: 0.036s

User time: 0.027s

Sys time: 0.009s

The third time sampling:

Real time: 0.037s

User time: 0.027s

Sys time: 0.009s

The fourth time sampling:

Real time: 0.036s

User time: 0.036s

Sys time: 0.000s

Comment:

I made another mistake and forgot to change the sampling size to 5000000 instead of the default of 500000.

I edit the vol5.h file with the correct value.

Result: -86
The compile time:

Real time: 0.098s

User time: 0.048s

Sys time: 0.046s

The first time sampling:

Real time: 0.037s

User time: 0.037s

Sys time: 0.000s

The second time sampling:

Real time: 0.038s

User time: 0.038s

Sys time: 0.000s

The third time sampling:

Real time: 0.035s

User time: 0.035s

Sys time: 0.000s

The fourth time sampling:

Real time: 0.036s

User time: 0.026s

Sys time: 0.010s

The fifth time sampling:

Real time: 0.036s

User time: 0.035s

Sys time: 0.000s

The sixth time sampling:

Real time: 0.036s

User time: 0.035s

Sys time: 0.001s

Comment:

This test, the Fifth Test, gives the fastest time for CPU, time to run/execute the program, and fastest time for the system to run/respond to the program.

Final Comment:

Performing the tests took longer but still got results. The results were from each method reduces or increases compile time or run time of sampling. The file size also increases each time the tests reduce in compile and run time. Basically sampling will only have two desired outcome of either lower file size or lower time of running or compiling the program.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s