586 lines
16 KiB
C
Executable File
586 lines
16 KiB
C
Executable File
/*
|
|
|
|
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 "audiobeamlibm.h"
|
|
#include "audiobeamlibmalloc.h"
|
|
#include "audiobeam.h"
|
|
|
|
/*
|
|
Forward declaration of functions
|
|
*/
|
|
|
|
void audiobeam_init();
|
|
int audiobeam_return();
|
|
void audiobeam_main( void );
|
|
int main( void );
|
|
void audiobeam_preprocess_delays( struct audiobeam_PreprocessedDelays
|
|
prep_delays[ ], float *delays );
|
|
float *audiobeam_parse_line( float *float_arr, int num_mic );
|
|
long int audiobeam_find_max_in_arr( float *arr, int size );
|
|
long int audiobeam_find_min_in_arr( float *arr, int size );
|
|
int audiobeam_wrapped_inc_offset( int i, int offset, int max_i );
|
|
int audiobeam_wrapped_dec_offset( int i, int offset, int max_i );
|
|
int audiobeam_wrapped_inc( int i, int max_i );
|
|
int audiobeam_wrapped_dec( int i, int max_i );
|
|
struct audiobeam_DataQueue *audiobeam_init_data_queue( int max_delay,
|
|
int num_mic );
|
|
struct audiobeam_Delays *audiobeam_init_delays ( int num_angles, int num_mic );
|
|
void audiobeam_calc_distances( float *source_location,
|
|
float audiobeam_mic_locations[ 15 ][ 3 ],
|
|
float *distances,
|
|
int num_mic );
|
|
void audiobeam_calc_delays( float *distances, float *delays, int sound_speed,
|
|
int sampling_rate, int num_mic );
|
|
void audiobeam_adjust_delays( float *delays, int num_mic );
|
|
float *audiobeam_calc_weights_lr ( int num_mic );
|
|
float *audiobeam_calc_weights_left_only ( int num_mic );
|
|
float audiobeam_calculate_energy( float *samples, int num_samples );
|
|
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 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 audiobeam_calc_beamforming_result( struct audiobeam_Delays *delays,
|
|
float **beamform_results,
|
|
float *energies,
|
|
struct audiobeam_DataQueue *queue,
|
|
int num_beams, int window,
|
|
int hamming );
|
|
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
|
|
*/
|
|
|
|
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 min 23040 max 23040" )
|
|
for ( i = 0; i < sizeof( audiobeam_input ); ++i, ++p )
|
|
*p ^= bitmask;
|
|
|
|
p = ( unsigned char * ) &audiobeam_mic_locations[ 0 ];
|
|
_Pragma( "loopbound min 180 max 180" )
|
|
for ( i = 0; i < sizeof( audiobeam_mic_locations ); ++i, ++p )
|
|
*p ^= bitmask;
|
|
|
|
p = ( unsigned char * ) &audiobeam_source_location[ 0 ];
|
|
_Pragma( "loopbound min 12 max 12" )
|
|
for ( i = 0; i < sizeof( audiobeam_source_location ); ++i, ++p )
|
|
*p ^= bitmask;
|
|
|
|
p = ( unsigned char * ) &audiobeam_origin_location[ 0 ];
|
|
_Pragma( "loopbound min 12 max 12" )
|
|
for ( i = 0; i < sizeof( audiobeam_origin_location ); ++i, ++p )
|
|
*p ^= bitmask;
|
|
}
|
|
|
|
|
|
int audiobeam_return()
|
|
{
|
|
return ( audiobeam_checksum + 1 != 0 );
|
|
}
|
|
|
|
|
|
/*
|
|
Algorithm core functions
|
|
*/
|
|
|
|
void audiobeam_preprocess_delays( struct audiobeam_PreprocessedDelays
|
|
prep_delays[ ], float *delays )
|
|
{
|
|
int i;
|
|
|
|
_Pragma( "loopbound min 15 max 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;
|
|
}
|
|
}
|
|
|
|
|
|
float *audiobeam_parse_line( float *float_arr, int num_mic )
|
|
{
|
|
int i;
|
|
|
|
_Pragma( "loopbound min 15 max 15" )
|
|
for ( i = 0; i < num_mic; i++ )
|
|
float_arr[ i ] = audiobeam_input[ audiobeam_input_pos++ ];
|
|
|
|
return float_arr;
|
|
}
|
|
|
|
|
|
long int audiobeam_find_max_in_arr( float *arr, int size )
|
|
{
|
|
int i;
|
|
float max = 0;
|
|
|
|
_Pragma( "loopbound min 15 max 15" )
|
|
for ( i = 0; i < size; i++ ) {
|
|
if ( arr[ i ] > max )
|
|
max = arr[ i ];
|
|
}
|
|
|
|
return audiobeam_ceil( max );
|
|
}
|
|
|
|
|
|
long int audiobeam_find_min_in_arr( float *arr, int size )
|
|
{
|
|
int i;
|
|
float min = arr[ 0 ];
|
|
|
|
_Pragma( "loopbound min 15 max 15" )
|
|
for ( i = 0; i < size; i++ ) {
|
|
if ( arr[ i ] < min )
|
|
min = arr[ i ];
|
|
}
|
|
|
|
return audiobeam_floor( min );
|
|
}
|
|
|
|
|
|
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 );
|
|
}
|
|
|
|
|
|
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 );
|
|
}
|
|
|
|
|
|
int audiobeam_wrapped_inc( int i, int max_i )
|
|
{
|
|
return audiobeam_wrapped_inc_offset( i, 1, max_i );
|
|
}
|
|
|
|
|
|
int audiobeam_wrapped_dec( int i, int max_i )
|
|
{
|
|
return audiobeam_wrapped_dec_offset( i, 1, max_i );
|
|
}
|
|
|
|
|
|
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 min 15 max 15" )
|
|
for ( i = 0; i < ( max_delay + 1 ); i++ ) {
|
|
( queue->sample_queue )[ i ] = ( float * ) audiobeam_malloc( num_mic
|
|
* sizeof( float ) );
|
|
_Pragma( "loopbound min 15 max 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;
|
|
}
|
|
|
|
|
|
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 min 1 max 1" )
|
|
for ( i = 0; i < ( num_angles ); i++ ) {
|
|
delays->delay_values[ i ] = ( float * ) audiobeam_malloc( num_mic
|
|
* sizeof( float ) );
|
|
}
|
|
|
|
return delays;
|
|
}
|
|
|
|
void audiobeam_calc_distances( float *source_location,
|
|
float audiobeam_mic_locations[ 15 ][ 3 ],
|
|
float *distances,
|
|
int num_mic )
|
|
{
|
|
int i;
|
|
|
|
_Pragma( "loopbound min 15 max 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 ] ) ) );
|
|
}
|
|
}
|
|
|
|
|
|
void audiobeam_calc_delays( float *distances, float *delays, int sound_speed,
|
|
int sampling_rate, int num_mic )
|
|
{
|
|
int i;
|
|
|
|
_Pragma( "loopbound min 15 max 15" )
|
|
for ( i = 0; i < num_mic; i++ )
|
|
delays[ i ] = ( distances[ i ] / sound_speed ) * sampling_rate;
|
|
}
|
|
|
|
|
|
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 min 15 max 15" )
|
|
for ( i = 0; i < num_mic; i++ )
|
|
delays[ i ] -= min_delay;
|
|
}
|
|
|
|
|
|
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 min 0 max 0" )
|
|
for ( z = 1; z >= -1; z -= 2 ) {
|
|
_Pragma( "loopbound min 0 max 0" )
|
|
for ( y = 0; y < half; y++ ) {
|
|
weights[ index ] = 0.54 + 0.46 * audiobeam_cos( audiobeam_M_PI * y
|
|
/ half );
|
|
index++;
|
|
}
|
|
_Pragma( "loopbound min 0 max 0" )
|
|
for ( y = 0; y < half; y++ ) {
|
|
weights[ index ] = 0.54 + 0.46 * audiobeam_cos( audiobeam_M_PI * ( -y )
|
|
/ half );
|
|
index++;
|
|
}
|
|
}
|
|
|
|
return weights;
|
|
}
|
|
|
|
|
|
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 min 15 max 15" )
|
|
for ( y = -half; y <= half; y++ ) {
|
|
weights[ index ] = 0.54 + 0.46 * audiobeam_cos( audiobeam_M_PI * y / half );
|
|
index++;
|
|
}
|
|
|
|
return weights;
|
|
}
|
|
|
|
|
|
float audiobeam_calculate_energy( float *samples, int num_samples )
|
|
{
|
|
int i;
|
|
float sum = 0.0;
|
|
|
|
_Pragma( "loopbound min 0 max 0" )
|
|
for ( i = 0; i < num_samples; i++ )
|
|
sum += ( samples[ i ] * samples[ i ] );
|
|
|
|
return sum;
|
|
}
|
|
|
|
|
|
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 min 15 max 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;
|
|
|
|
}
|
|
|
|
|
|
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 min 13 max 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 min 371 max 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 min 1 max 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 );
|
|
}
|
|
|
|
|
|
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 min 1 max 1" )
|
|
for ( i = 0; i < num_beams; i++ )
|
|
energies[ i ] = audiobeam_calculate_energy( beamform_results[ i ], window );
|
|
}
|
|
return done;
|
|
}
|
|
|
|
|
|
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
|
|
*/
|
|
|
|
void _Pragma( "entrypoint" ) audiobeam_main( void )
|
|
{
|
|
char hamming = 1;
|
|
audiobeam_calc_single_pos( audiobeam_source_location,
|
|
audiobeam_mic_locations,
|
|
hamming );
|
|
}
|
|
|
|
|
|
int main( void )
|
|
{
|
|
audiobeam_init();
|
|
audiobeam_main();
|
|
|
|
return ( audiobeam_return() );
|
|
}
|
|
|