2

Background: I am interested in localizing a sound source from a suite of audio recorders. Each audio array consists of 6 directional microphones spaced evenly every 60 degrees (0, 60, 120, 180, 240, 300 degrees). I am interested in finding the neighboring pair of microphones with the maximum set of signal strengths. Data consists of a time stamp, antenna number and bearing, and signal strength. Below I have attached a simplified dataset.

    df <- data.frame(ant.bearing = seq(0,300, by=60), sig = c(98, 60, 44, 67, 58, 91), ts=1)

Goals: From this dataset, I would like use a function to extract the two neighboring antennas with the maximal set of signal strengths (i.e. antennas with bearings 0 and 300 degrees in above sample code) while accounting for the fact that this data is circular in nature and antennas 0 and 300 are neighbors. Output would be the two rows of data that satisfy the above task e.g. rows 1 and 6 in the above case.

What I've tried:

direction.finder <- function(dat){
    # finding bearing with max signal strength
    max <- dat[dat$sig == max(dat$sig),][1,]

    # finding signal strengths of neighbor antennas and pulling out which has highest

    left  = dat[dat$ant.bearing==max$ant.bearing-60,]
    right = dat[dat$ant.bearing==max$ant.bearing+60,]

    if(max$ant.bearing==0)
        left = dat[dat$ant.bearing==300,]
    if(max$ant.bearing==300)
        right = dat[dat$ant.bearing==0,]

    sub = right

    if(left$sig > right$sig)
        sub = left

    dat <- rbind(max, sub)
} 

This current function serves as an okay workaround for my task but its not ideal. Any suggestions or tips for improving the functionality of my code would be greatly appreciated.

1 Answers1

2

I would compute all the pairs of rows in df:

(pairs <- cbind(1:nrow(df), c(2:nrow(df), 1)))
#      [,1] [,2]
# [1,]    1    2
# [2,]    2    3
# [3,]    3    4
# [4,]    4    5
# [5,]    5    6
# [6,]    6    1

You can find the best pairing with which.max:

(best.row <- which.max(df$sig[pairs[,1]] + df$sig[pairs[,2]]))
# [1] 6

Finally, you can look up the corresponding antenna bearings:

df$ant.bearing[pairs[best.row,]]
# [1] 300   0

If you had missing values, you could slightly adjust the code by creating NA values for the missing entries:

# Data
df <- data.frame(ant.bearing = seq(0,180, by=60), sig = c(44, 67,88, 52), ts=2)
#   ant.bearing sig ts
# 1           0  44  2
# 2          60  67  2
# 3         120  88  2
# 4         180  52  2

(pairs <- cbind(1:6, c(2:6, 1)))
#      [,1] [,2]
# [1,]    1    2
# [2,]    2    3
# [3,]    3    4
# [4,]    4    5
# [5,]    5    6
# [6,]    6    1

sig <- rep(NA, 6)
sig[1+df$ant.bearing/60] <- df$sig
sig
# [1] 44 67 88 52 NA NA

Now the rest of the process is similar:

(best.row <- which.max(sig[pairs[,1]] + sig[pairs[,2]]))
# [1] 2
60*(pairs[best.row,]-1)
# [1]  60 120
josliber
  • 43,891
  • 12
  • 98
  • 133