Question Time delay estimation of two signals?

mashw

New member
Joined
Nov 27, 2022
Messages
3
Programming Experience
Beginner
I've written an program in python to estimate the time delay of two signals by converting a WAV file in different numpy arrays and cross calculating them to get the time delay. But is the same thing possible in C#. Are there any libraries available for this.
 
Did you really write the Python code to calculate the time delay? Or did you just write code to make calls to NumPy library to do the calculation? If you actually wrote the code then it's just a matter of porting the Python code to C#. If what you wrote is dependent on NumPy, then you'll need to find a numerics library that has those specific functions that you need. Since you didn't describe what specific functions you used, your question about availability of libraries is kind of open ended.
 
Did you really write the Python code to calculate the time delay? Or did you just write code to make calls to NumPy library to do the calculation? If you actually wrote the code then it's just a matter of porting the Python code to C#. If what you wrote is dependent on NumPy, then you'll need to find a numerics library that has those specific functions that you need. Since you didn't describe what specific functions you used, your question about availability of libraries is kind of open ended.
I cross calculated the arrays which I obtained by reading in a 2 channel wav file and converting them to arrays to obtain the time delay of two signals. It's for a project, we've designed an app in Xamarin to display the angle of arrival of a sound. We first wanted to see if our way of calculating worked in python and maybe use an API to get the output of this python program but hoped that there would be any packages/libraries available in C# to help it. My knowledge of C# is very limited, hence the question on the forum.
 
We'll, if your Python program outputs to standard output, you can use the framework to execute your program and then read the output.

I'm not sure what Xamarin has to do with this, though. Unless you are planning on doing something like a DIY gun shot detector to run on a mobile device. In that case, I have no idea if you can run your Python program on the phone and then get the output from its console output.

You still did not tell us what functions from NumPy you are using.

As it stands right now, it seems to me all you need to do is just find the first peak of each of the channels. Since WAV files have fixed sample rates, you know when those peaks occurs by simple multiplication of the sample rate with the offset into the channel data. Then from there you need to know the distance between the two microphones that recorded the two channels. With a little bit of trigonometry and assumptions about the speed of sound in air and the current temperature, you can determine the direction that the signal came from.
 
The Python fan at work mentioned that NumPy is being ported to C# (and wil a speed boost too) ..

What it's called I've no idea
 
Last edited:
We'll, if your Python program outputs to standard output, you can use the framework to execute your program and then read the output.

I'm not sure what Xamarin has to do with this, though. Unless you are planning on doing something like a DIY gun shot detector to run on a mobile device. In that case, I have no idea if you can run your Python program on the phone and then get the output from its console output.

You still did not tell us what functions from NumPy you are using.

As it stands right now, it seems to me all you need to do is just find the first peak of each of the channels. Since WAV files have fixed sample rates, you know when those peaks occurs by simple multiplication of the sample rate with the offset into the channel data. Then from there you need to know the distance between the two microphones that recorded the two channels. With a little bit of trigonometry and assumptions about the speed of sound in air and the current temperature, you can determine the direction that the signal came from.
This is the code I have written! Sorry for the delay of showing it. As you can see, it's just saving the channels of the wav file in seperate files and then converting the wav file to an array to then finally determine the delay between the signals by cross calculating them. I have little knowledge about C# but I just have to show the output of this program in the App built with Xamarin, hence the C#. So i don't know if I could write this exact program in C#, or maybe an API would be better of...
Thanks for your help!

Python:
import wave as wv
import numpy as np
import matplotlib.pyplot as plt
from scipy.io.wavfile import read
  #import used libraries

#function that converts .WAV file to np_array
def MakeArray(file):
  # Read in file                                                                                               
  ifile = wave.open(file)
  samples = ifile.getnframes()
  audio = ifile.readframes(samples)


  # Conversion to float32                                                                             
  audio_as_np_int16 = np.frombuffer(audio, dtype=np.int16)
  audio_as_np_float32 = audio_as_np_int16.astype(np.float32)

  # Normalisation                                                       
  max_int16 = 2**15
  audio_normalised = audio_as_np_float32 / max_int16

  return audio_normalised
#function that seprates the channels from a .WAV file

def save_wav_channel(fn, wav, channel):
    #fn stands for file name on which the seperated channel needs to be save, wav sgtays the same and channel is nth channel it has seperated

    # Read data
    nch   = wav.getnchannels()
    depth = wav.getsampwidth()
    wav.setpos(0)
    sdata = wav.readframes(wav.getnframes())

    # Extract channel data (24-bit data not supported)
    typ = { 1: np.uint8, 2: np.uint16, 4: np.uint32 }.get(depth)
    if not typ:
        raise ValueError("sample width {} not supported".format(depth))
    if channel >= nch:
        raise ValueError("cannot extract channel {} out of {}".format(channel+1, nch))
    print ("Extracting channel {} out of {} channels, {}-bit depth".format(channel+1, nch, depth*8))
    data = np.fromstring(sdata, dtype=typ)
    ch_data = data[channel::nch]

    # Save channel to a separate file
    outwav = wave.open(fn, 'w')
    outwav.setparams(wav.getparams())
    outwav.setnchannels(1)
    outwav.writeframes(ch_data.tostring())
    outwav.close()
    
wav = wave.open("/content/test3.wav")
save_wav_channel('T1.wav', wav, 0)
save_wav_channel('T2.wav', wav, 1)

import matplotlib.pyplot as plt
from scipy import signal
import numpy as np


def lag_finder(y1, y2, sr):
    n = len(y1)

    corr = signal.correlate(y2, y1, mode='same') / np.sqrt(signal.correlate(y1, y1, mode='same')[int(n/2)] * signal.correlate(y2, y2, mode='same')[int(n/2)])

    delay_arr = np.linspace(-0.5*n/sr, 0.5*n/sr, n)
    delay = delay_arr[np.argmax(corr)]
    print('y2 is ' + str(delay) + ' behind y1')

    plt.figure()
    plt.plot(delay_arr, corr)
    plt.title('Lag: ' + str(delay) + ' s')
    plt.xlabel('Lag')
    plt.ylabel('Correlation coeff')
    plt.show()
    print(np.argmax(corr))
    return delay
a= MakeArray("/content/T1.wav")
b= MakeArray("/content/T2.wav")


d =lag_finder(a,b,48000)

print(d)

alpha = d*343/0.50
print(alpha)
angle = np.arcsin(alpha)
print()
degree = angle*180/(3.14)
print(str(degree) +"°")
 
Looks like you more than just a dependency on Numpy. You also depend on SciPy as well as Wave.

Just doing a 5 minute scan of your code and lookups on Google, it looks like SciPy.correlate() could just be implemented using the standard statistical method using sums, unless you really want to implement a Fast Fourier Transform to get the correlation. You don't really need NumPy.linspace. This could be replaced with just a simple linear interpolation.

Reading a .WAV file is pretty easy since the format gives you uncompressed data. Normalizing the values is simple division on the data as you read it in, but I don't think you need to do any kind of normalization on it since the values are all within a fixed range, and all you need to do is find the index of the highest value of the correlation between the two channels.
 
Back
Top Bottom