Files
failnix/targets/wasm-tacle/sequential/audiobeam/generated/modified_sources/inline/audiobeam.c

570 lines
18 KiB
C

/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeam
Author: Eugene Weinstein
Function: Audio beam former
Source: StreamIt
http://groups.csail.mit.edu/cag/streamit/
Changes: no functional changes
License: see license.txt
*/
/*
Include section
*/
#include "audiobeam.h"
#include "audiobeamlibm.h"
#include "audiobeamlibmalloc.h"
/*
Forward declaration of functions
*/
// Wasm loop bounds
#include "audiobeaminput.c"
#include "audiobeamlibm.c"
#include "audiobeamlibmalloc.c"
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
__attribute__((always_inline)) static inline void audiobeam_init();
__attribute__((always_inline)) static inline int audiobeam_return();
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
audiobeam_main(void);
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void);
__attribute__((always_inline)) static inline void
audiobeam_preprocess_delays(struct audiobeam_PreprocessedDelays prep_delays[],
float *delays);
__attribute__((always_inline)) static inline float *
audiobeam_parse_line(float *float_arr, int num_mic);
__attribute__((always_inline)) static inline long int
audiobeam_find_max_in_arr(float *arr, int size);
__attribute__((always_inline)) static inline long int
audiobeam_find_min_in_arr(float *arr, int size);
__attribute__((always_inline)) static inline int
audiobeam_wrapped_inc_offset(int i, int offset, int max_i);
__attribute__((always_inline)) static inline int
audiobeam_wrapped_dec_offset(int i, int offset, int max_i);
__attribute__((always_inline)) static inline int
audiobeam_wrapped_inc(int i, int max_i);
__attribute__((always_inline)) static inline int
audiobeam_wrapped_dec(int i, int max_i);
__attribute__((always_inline)) static inline struct audiobeam_DataQueue *
audiobeam_init_data_queue(int max_delay, int num_mic);
__attribute__((always_inline)) static inline struct audiobeam_Delays *
audiobeam_init_delays(int num_angles, int num_mic);
__attribute__((always_inline)) static inline void
audiobeam_calc_distances(float *source_location,
float audiobeam_mic_locations[15][3], float *distances,
int num_mic);
__attribute__((always_inline)) static inline void
audiobeam_calc_delays(float *distances, float *delays, int sound_speed,
int sampling_rate, int num_mic);
__attribute__((always_inline)) static inline void
audiobeam_adjust_delays(float *delays, int num_mic);
__attribute__((always_inline)) static inline float *
audiobeam_calc_weights_lr(int num_mic);
__attribute__((always_inline)) static inline float *
audiobeam_calc_weights_left_only(int num_mic);
__attribute__((always_inline)) static inline float
audiobeam_calculate_energy(float *samples, int num_samples);
__attribute__((always_inline)) static inline float audiobeam_do_beamforming(
struct audiobeam_PreprocessedDelays preprocessed_delays[],
float **sample_queue, int queue_head, long int max_delay, int num_mic,
float *weights);
__attribute__((always_inline)) static inline int
audiobeam_process_signal(struct audiobeam_Delays *delays, int num_mic,
float sampling_rate, float **beamform_results,
struct audiobeam_DataQueue *queue, int num_beams,
int window, float *weights);
__attribute__((always_inline)) static inline int
audiobeam_calc_beamforming_result(struct audiobeam_Delays *delays,
float **beamform_results, float *energies,
struct audiobeam_DataQueue *queue,
int num_beams, int window, int hamming);
__attribute__((always_inline)) static inline void
audiobeam_calc_single_pos(float source_location[3],
float audiobeam_mic_locations[15][3], int hamming);
/*
Declaration of global variables
*/
extern float audiobeam_input[5760];
extern float audiobeam_mic_locations[15][3];
extern float audiobeam_source_location[3];
extern float audiobeam_origin_location[3];
int audiobeam_input_pos;
int audiobeam_checksum;
/*
Initialization- and return-value-related functions
*/
__attribute__((always_inline)) static inline void
audiobeam_init() {
audiobeam_input_pos = 0;
audiobeam_checksum = 0;
unsigned int i;
unsigned char *p;
volatile char bitmask = 0;
/*
Apply volatile XOR-bitmask to entire input array.
*/
p = (unsigned char *) &audiobeam_input[0];
__pragma_loopbound(23040, 23040);
for (i = 0; i < sizeof(audiobeam_input); ++i, ++p)
*p ^= bitmask;
p = (unsigned char *) &audiobeam_mic_locations[0];
__pragma_loopbound(180, 180);
for (i = 0; i < sizeof(audiobeam_mic_locations); ++i, ++p)
*p ^= bitmask;
p = (unsigned char *) &audiobeam_source_location[0];
__pragma_loopbound(12, 12);
for (i = 0; i < sizeof(audiobeam_source_location); ++i, ++p)
*p ^= bitmask;
p = (unsigned char *) &audiobeam_origin_location[0];
__pragma_loopbound(12, 12);
for (i = 0; i < sizeof(audiobeam_origin_location); ++i, ++p)
*p ^= bitmask;
}
__attribute__((always_inline)) static inline int
audiobeam_return() {
return (audiobeam_checksum + 1 != 0);
}
/*
Algorithm core functions
*/
__attribute__((always_inline)) static inline void
audiobeam_preprocess_delays(struct audiobeam_PreprocessedDelays prep_delays[],
float *delays) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < 15; i++) {
prep_delays[i].delay = delays[i];
prep_delays[i].high = (int) audiobeam_ceil(delays[i]);
prep_delays[i].low = (int) audiobeam_floor(delays[i]);
prep_delays[i].offset = delays[i] - prep_delays[i].low;
}
}
__attribute__((always_inline)) static inline float *
audiobeam_parse_line(float *float_arr, int num_mic) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++)
float_arr[i] = audiobeam_input[audiobeam_input_pos++];
return float_arr;
}
__attribute__((always_inline)) static inline long int
audiobeam_find_max_in_arr(float *arr, int size) {
int i;
float max = 0;
__pragma_loopbound(15, 15);
for (i = 0; i < size; i++) {
if (arr[i] > max)
max = arr[i];
}
return audiobeam_ceil(max);
}
__attribute__((always_inline)) static inline long int
audiobeam_find_min_in_arr(float *arr, int size) {
int i;
float min = arr[0];
__pragma_loopbound(15, 15);
for (i = 0; i < size; i++) {
if (arr[i] < min)
min = arr[i];
}
return audiobeam_floor(min);
}
__attribute__((always_inline)) static inline int
audiobeam_wrapped_inc_offset(int i, int offset, int max_i) {
if (i + offset > max_i)
return (i + offset - max_i - 1);
else
return (i + offset);
}
__attribute__((always_inline)) static inline int
audiobeam_wrapped_dec_offset(int i, int offset, int max_i) {
if (i - offset < 0)
return (max_i - (offset - i) + 1);
else
return (i - offset);
}
__attribute__((always_inline)) static inline int
audiobeam_wrapped_inc(int i, int max_i) {
return audiobeam_wrapped_inc_offset(i, 1, max_i);
}
__attribute__((always_inline)) static inline int
audiobeam_wrapped_dec(int i, int max_i) {
return audiobeam_wrapped_dec_offset(i, 1, max_i);
}
__attribute__((always_inline)) static inline struct audiobeam_DataQueue *
audiobeam_init_data_queue(int max_delay, int num_mic) {
int i, j;
struct audiobeam_DataQueue *queue;
queue = (struct audiobeam_DataQueue *) audiobeam_malloc(
sizeof(struct audiobeam_DataQueue));
queue->sample_queue =
(float **) audiobeam_malloc((max_delay + 1) * sizeof(float *));
__pragma_loopbound(15, 15);
for (i = 0; i < (max_delay + 1); i++) {
(queue->sample_queue)[i] =
(float *) audiobeam_malloc(num_mic * sizeof(float));
__pragma_loopbound(15, 15);
for (j = 0; j < num_mic; j++) {
(queue->sample_queue)[i][j] = 0.0; // Initialize values to 0
}
}
queue->head = 0;
queue->tail = 0;
queue->full = 0;
return queue;
}
__attribute__((always_inline)) static inline struct audiobeam_Delays *
audiobeam_init_delays(int num_angles, int num_mic) {
struct audiobeam_Delays *delays;
int i;
delays = (struct audiobeam_Delays *) audiobeam_malloc(
sizeof(struct audiobeam_Delays));
// Initialize the delays array
delays->delay_values =
(float **) audiobeam_malloc(num_angles * sizeof(float *));
__pragma_loopbound(1, 1);
for (i = 0; i < (num_angles); i++) {
delays->delay_values[i] =
(float *) audiobeam_malloc(num_mic * sizeof(float));
}
return delays;
}
__attribute__((always_inline)) static inline void
audiobeam_calc_distances(float *source_location,
float audiobeam_mic_locations[15][3], float *distances,
int num_mic) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++) {
distances[i] = (audiobeam_sqrt(
(audiobeam_mic_locations[i][0] - source_location[0]) *
(audiobeam_mic_locations[i][0] - source_location[0]) +
(audiobeam_mic_locations[i][1] - source_location[1]) *
(audiobeam_mic_locations[i][1] - source_location[1]) +
(audiobeam_mic_locations[i][2] - source_location[2]) *
(audiobeam_mic_locations[i][2] - source_location[2])));
}
}
__attribute__((always_inline)) static inline void
audiobeam_calc_delays(float *distances, float *delays, int sound_speed,
int sampling_rate, int num_mic) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++)
delays[i] = (distances[i] / sound_speed) * sampling_rate;
}
__attribute__((always_inline)) static inline void
audiobeam_adjust_delays(float *delays, int num_mic) {
int i;
long int min_delay = audiobeam_find_min_in_arr(delays, num_mic) - 1;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++)
delays[i] -= min_delay;
}
__attribute__((always_inline)) static inline float *
audiobeam_calc_weights_lr(int num_mic) {
float *weights = (float *) audiobeam_malloc(num_mic * sizeof(float));
int index = 0;
int y, z;
int half = num_mic / 4;
__pragma_loopbound(0, 0);
for (z = 1; z >= -1; z -= 2) {
__pragma_loopbound(0, 0);
for (y = 0; y < half; y++) {
weights[index] =
0.54 + 0.46 * audiobeam_cos(audiobeam_M_PI * y / half);
index++;
}
__pragma_loopbound(0, 0);
for (y = 0; y < half; y++) {
weights[index] =
0.54 + 0.46 * audiobeam_cos(audiobeam_M_PI * (-y) / half);
index++;
}
}
return weights;
}
__attribute__((always_inline)) static inline float *
audiobeam_calc_weights_left_only(int num_mic) {
float *weights = (float *) audiobeam_malloc(num_mic * sizeof(float));
int index = 0;
int y;
int half = num_mic / 2;
__pragma_loopbound(15, 15);
for (y = -half; y <= half; y++) {
weights[index] = 0.54 + 0.46 * audiobeam_cos(audiobeam_M_PI * y / half);
index++;
}
return weights;
}
__attribute__((always_inline)) static inline float
audiobeam_calculate_energy(float *samples, int num_samples) {
int i;
float sum = 0.0;
__pragma_loopbound(0, 0);
for (i = 0; i < num_samples; i++)
sum += (samples[i] * samples[i]);
return sum;
}
__attribute__((always_inline)) static inline float
audiobeam_do_beamforming(
struct audiobeam_PreprocessedDelays preprocessed_delays[],
float **sample_queue, int queue_head, long int max_delay, int num_mic,
float *weights) {
int i;
float sum = 0;
int delay_floor;
int delay_ceil;
int low_index;
int high_index;
float interpolated_value;
// add up all the num_mic delayed samples
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++) {
delay_floor = preprocessed_delays[i].low;
delay_ceil = preprocessed_delays[i].high;
// Inline wrap around here
// Low index gets index of sample right before desired sample
low_index = queue_head + delay_floor;
if (low_index > max_delay)
low_index -= (max_delay + 1);
// High index gets index of sample right after desired sample
high_index = queue_head + delay_ceil;
if (high_index > max_delay)
high_index -= (max_delay + 1);
// i gives the value of the microphone we want. However, since
// the array only has microphones first_mic to last_mic, we
// need to offset our index by first_mic
interpolated_value =
(((sample_queue[high_index][i] - sample_queue[low_index][i]) *
(preprocessed_delays[i].offset)) +
sample_queue[low_index][i]);
// If we have microphone weights, multiply the value by the weight
if (weights != 0)
sum += (interpolated_value * weights[i]);
else
sum += interpolated_value;
}
return sum;
}
__attribute__((always_inline)) static inline int
audiobeam_process_signal(struct audiobeam_Delays *delays, int num_mic,
float sampling_rate, float **beamform_results,
struct audiobeam_DataQueue *queue, int num_beams,
int window, float *weights) {
int i, j;
float time_index = 0;
float time_index_inc = (1.0 / sampling_rate);
float value;
int done = 0;
struct audiobeam_PreprocessedDelays preprocessed_delays[15];
audiobeam_preprocess_delays(preprocessed_delays, delays->delay_values[0]);
__pragma_loopbound(13, 13);
for (i = 0; i < delays->max_delay - 1; i++) {
if (audiobeam_input_pos < 5760)
audiobeam_parse_line((queue->sample_queue)[queue->head], 15);
else
return -1;
queue->head = audiobeam_wrapped_inc(queue->head, delays->max_delay);
}
__pragma_loopbound(371, 371);
for (i = 0; (i < window) || (window < 0); i++) {
if (audiobeam_input_pos < 5760)
audiobeam_parse_line((queue->sample_queue)[queue->head], 15);
else {
done = 1;
break;
}
__pragma_loopbound(1, 1);
for (j = 0; j < num_beams; j++) {
value = audiobeam_do_beamforming(
preprocessed_delays, (queue->sample_queue),
audiobeam_wrapped_inc(queue->head, delays->max_delay),
delays->max_delay, num_mic, weights);
value = value / num_mic;
if (beamform_results != 0)
beamform_results[j][i] = value;
}
queue->tail = queue->head;
queue->head = audiobeam_wrapped_inc(queue->head, delays->max_delay);
time_index += time_index_inc;
}
return (done);
}
__attribute__((always_inline)) static inline int
audiobeam_calc_beamforming_result(struct audiobeam_Delays *delays,
float **beamform_results, float *energies,
struct audiobeam_DataQueue *queue,
int num_beams, int window, int hamming) {
int i;
int done;
float *weights = 0;
if (hamming) {
if ((15 % 2) == 1)
weights = audiobeam_calc_weights_left_only(15);
else
weights = audiobeam_calc_weights_lr(15);
}
done = audiobeam_process_signal(delays, 15, 16000, beamform_results, queue,
num_beams, window, weights);
if (beamform_results != 0) {
__pragma_loopbound(1, 1);
for (i = 0; i < num_beams; i++)
energies[i] =
audiobeam_calculate_energy(beamform_results[i], window);
}
return done;
}
__attribute__((always_inline)) static inline void
audiobeam_calc_single_pos(float source_location[3],
float audiobeam_mic_locations[15][3], int hamming) {
float mic_distances[15];
struct audiobeam_Delays *delays = audiobeam_init_delays(1, 15);
struct audiobeam_DataQueue *queue;
float **beamform_results;
float *energies;
beamform_results = (float **) audiobeam_malloc(1 * sizeof(float *));
beamform_results[0] = (float *) audiobeam_malloc(384 * sizeof(float));
energies = (float *) audiobeam_malloc(1 * sizeof(float *));
// Calculate distances from source to each of mics
audiobeam_calc_distances(source_location, audiobeam_mic_locations,
mic_distances, 15);
audiobeam_calc_delays(mic_distances, delays->delay_values[0], 342, 16000,
15);
audiobeam_adjust_delays(delays->delay_values[0], 15);
delays->max_delay = audiobeam_find_max_in_arr(delays->delay_values[0], 15);
queue = audiobeam_init_data_queue(delays->max_delay, 15);
audiobeam_calc_beamforming_result(delays, beamform_results, energies, queue,
1, -1, hamming);
audiobeam_checksum += beamform_results[0][0] * 1000;
}
/*
Main functions
*/
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
audiobeam_main(void) {
char hamming = 1;
audiobeam_calc_single_pos(audiobeam_source_location,
audiobeam_mic_locations, hamming);
}
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
audiobeam_init();
audiobeam_main();
return (audiobeam_return());
}