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]];
- 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.
- 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.
- 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.