Skip to main content

Lab 5

In this lab, we are going to use different approaches to scale volume of sound, and the algorithm’s effect on system performance. Here is some basic knowledge of digital sound: Digital sound is usually represented by a signed 16-bit integer signal sample, taken at a rate of around 44.1 or 48 thousand samples per second for one stream of samples for the left and right stereo channels. In order to change the volume of sound, we will have to scale the volume factor for each sample, the range of 0.00 to 1.00 (silence to full volume).

Here is the source code I got from professor: (vol1.h)
-------------------------------------------------
#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;

}
-------------------------------------------------
And 500,000 random "sound samples" stored in (vol.h)

When I build and test the file, I got the same output each time:
-------------------------------------------------
[qichang@aarchie spo600_20181_vol_skel]$ ./vol1
Result: -238
[qichang@aarchie spo600_20181_vol_skel]$ ./vol1
Result: -238
[qichang@aarchie spo600_20181_vol_skel]$ ./vol1
Result: -238
-------------------------------------------------

In order to count how much time spent scaling the sound samples, I added a start function and end function during scaling function.
-------------------------------------------------
start = clock();
// ######################################
// 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);
}
// ######################################
end = clock();
total = end - start;
-------------------------------------------------

Rebuild and re-test the file, I got the output: (without samples changed)
-------------------------------------------------
[qichang@aarchie spo600_20181_vol_skel]$ ./vol1
Result: -126
Time spending for scaling the sound samples: 0.000977 seconds.
[qichang@aarchie spo600_20181_vol_skel]$ ./vol1
Result: -126
Time spending for scaling the sound samples: 0.000959 seconds.
[qichang@aarchie spo600_20181_vol_skel]$ ./vol1
Result: -126
Time spending for scaling the sound samples: 0.000981 seconds.
-------------------------------------------------

And the output of changed the sound samples to 500000:
-------------------------------------------------
[qichang@aarchie spo600_20181_vol_skel]$ ./vol1
Result: 956
Time spending for scaling the sound samples: 0.010667 seconds.
[qichang@aarchie spo600_20181_vol_skel]$ ./vol1
Result: 956
Time spending for scaling the sound samples: 0.010774 seconds.
[qichang@aarchie spo600_20181_vol_skel]$ ./vol1
Result: 956
Time spending for scaling the sound samples: 0.010717 seconds.
-------------------------------------------------

Obviously, the spending time is increased but sums the output array is the same.

Next, we are going to pre-calculate a lookup table of all possible sample values multiplied by the volume factor and look up each sample in that table to get the scaled values.
Here is the source code I modefied from vol1.c:
-------------------------------------------------
[qichang@aarchie spo600_20181_vol_skel]$ cat vol2.c
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "vol.h"
#include <time.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;
int16_t* lookupTable = calloc(65536, sizeof(int16_t));
in = (int16_t*) calloc(SAMPLES, sizeof(int16_t));
out = (int16_t*) calloc(SAMPLES, sizeof(int16_t));

int x;
int ttl;
clock_t start, end, total;

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

// Initialize lookup table by multiplied by the volume factor
for(int i=0; i<65536; i++){
lookupTable[i] = (i-32768) * 0.75;
}

start = clock();

// ######################################
// 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++) {
in[x] = (lookupTable[in[x] + 32768]);
ttl = (ttl+out[x])%1000;
}
end = clock();
        total = end - start;

for(int i =0; i<10; i++){
printf("%d \n", in[i]);
}
// Print the sum
printf("Result: %d\n", ttl);
printf("Time spending for scaling the sound samples: %f seconds.\n",
        (float) total/CLOCKS_PER_SEC);
return 0;

}
-------------------------------------------------

And the output is:
-------------------------------------------------
[qichang@aarchie spo600_20181_vol_skel]$ ./vol2
17516
10521
8070
12072
-789
9538
1708
-15747
-20292
-15138
Result: -414
Time spending for scaling the sound samples: 0.003499 seconds.
-------------------------------------------------

The program outputs the first 10 sound samples scaled to volume from the array, and then the sum of all 500,000 scaled sound samples, and finally the time is taken for the volume-scaling part.
As we see for these versions of scaling volume of sounds, using lookup table is much faster than the original one.

Comments

Popular posts from this blog

Lab2

Complied C Lab In this lab, we were asked to compile a C program, using gcc command with different options. At the beginning of this lab, we wrote a simple C program that prints a message: Then using gcc command and the following compiler options to compile the program: -g # enable debugging information -O0 # do not optimize (that's a capital letter and then the digit zero) -fno-builtin # do not use builtin function optimizations Note that the size of file is 73088 bytes We can use objdump --source a.out command to show source code, the source code is under <main> section. And  readelf -p .rodata a.out contains the string to be printed. Then we add the option "-static" to recompile the program, found out the size is changed to 696264 bytes, which is bigger than the original program. And section headers are also increased. Next, I removed the builtin function optimization by remove option "-fno-builtin"...

SPO600 - Project - Stage Three

In this last stage of my SPO600 project, Since I don't have results suitable for upstreaming, I am going to wrap up my project results and do some thorough technical analysis of my results. First of all, I am going to summary what I did for my project. (If you want to go over the details, you can see my previous posts.) I picked a software called SSDUP, it is a traffic-aware SSD burst buffer for HPC systems. I noticed that it uses 3 different Murmurhash3 hash functions, the first two hash functions are optimized for x86 platforms and the third hash function is optimized for x64 platforms. I also noticed that it uses 'gcc -std=gnu99' to compile. In order to easier to handler these 3 hash functions, I split them into 3 files and separately testing them on an AArch64 and x86_64 systems. As the professor said my results in stage two is hard to read, I am going to show my results again in a table format. First hash function (MurmurHash3_x86_32), the execution time for -O3...

SPO600 - Project - Stage One

In our final project, the project will split into 3 stages. This is the first stage of my SPO600 course project. In this stage, we are given a task to find an open source software package that includes a CPU-intensive function or method that compiles to machine code. After I chose the open source software package, I will have to benchmark the performance of the software function on an AArach64 system. When the benchmark job is completed, I will have to think about my strategy that attempts to optimize the hash function for better performance on an AArch64 system and identify it, because those strategies will be used in the second stage of the project. With so many software, I would say picking software is the hardest job in the project, which is the major reason it took me so long to get this post going. But after a lot of research, I picked a software called SSDUP , it is a traffic-aware SSD burst buffer for HPC systems. You can find the source code over here: https://github.com/CGC...