Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time delay when sound source is far away and amplitude of the signal #257

Open
shpark3312 opened this issue Apr 5, 2022 · 9 comments
Open

Comments

@shpark3312
Copy link

shpark3312 commented Apr 5, 2022

I am doing some experiment with pyroom acoustics.

Made a big room with one source and mic array with 0 max_order.
Distance from sound source and center of the mic array was set to 1000m, but the time delay i got was 0.47 sec.
And also I though that if the distance between source and mic become twice longer, the calculated amplitude of beamformed signal from the mic array should be reduced as well but got different result form the simulation by pyroomacoustics.

Am I doing some thing wrong?

@fakufaku
Copy link
Collaborator

fakufaku commented Apr 5, 2022

Oh! I've never made such a big room 🤯 Do you have a code fragment for me to try this out ?

@shpark3312
Copy link
Author

I just figured out that i made a mistake with sample rate when saving result signal.... time delay seems to be alright.

But Still having the amplitude of beamformed signal issue.

here is the code i am using

distance_list = [10, 50, 100, 500, 1000, 2000, 4000]
for distance in distance_list:
    room_dim=[5000,5000]
    room = pra.ShoeBox(
        room_dim,
        absorption=absorption,
        fs=Fs,
        max_order=max_order_sim,
        sigma2_awgn=sigma2_n,
        air_absorption = True
    )

    mic_center = [2500, 100]
    fft_len = 1024
    n_mics = 12
    R = DoughertyLogSpiral(mic_center, rmax = 0.15, rmin = 0.025, v = 87 *np.pi/180, n_mics = n_mics, direction = "2d")
    mics = pra.Beamformer(R, room.fs, N=fft_len, Lg=Lg)

    sig1_pos = [2500, mic_center[1] + distance]
    room.add_source(sig1_pos, delay=0., signal=signal1)

    # sig2_pos = [2500 + 3, mic_center[1]]
    # room.add_source(sig2_pos, delay=0., signal=signal2)


    room.add_microphone_array(mics)
    room.compute_rir()
    room.simulate()
    # room.plot()
    # plt.show()
    
    sf.write(f"./results/2d/beamforming/drone/all_mix_{distance}m.wav", room.mic_array.signals[-1,:].astype(np.int16),  Fs)

    room.mic_array.rake_perceptual_filters(room.sources[0][:2], None, R_n = sigma2_n * np.eye(mics.Lg * mics.M), delay = delay)

    fig, ax = room.plot(freq=[500, 1000, 2000, 3000, 4000, 5000, 6000], img_order=0)
    ax.legend(["500", "1000", "2000", "4000", "5000", "6000"])
    fig.set_size_inches(20, 8)
    # plt.show()

    signal_das = room.mic_array.process(FD=False)
    signal_das = np.array(signal_das/(4*n_mics), dtype=np.int16)

    print(f"distance = {distance:10f}, sig_max = {np.max(signal_das):10f}, sig_min = {np.min(signal_das):10f}, rms = {np.sqrt(np.mean(signal_das**2))}")
    sf.write(f"./results/2d/beamforming/drone/drone_test_source_0_{distance}m.wav", signal_das, Fs)

`

@fakufaku
Copy link
Collaborator

fakufaku commented Apr 5, 2022

Good that you figured out the delay issue! 👏

For the amplitude, it is actually the energy that reduced by the square of the distance. The amplitude is reduced inversely proportional to the distance. Can you please check the energy ? Also, this is true only in anechoic conditions, but that would be the case with max_order=0.

@shpark3312
Copy link
Author

I checked the energy also but didn't get the result we thought.

signal_das = room.mic_array.process(FD=False)
signal_das = np.array(signal_das/4, dtype=np.int16)
rms = np.sqrt(np.mean(signal_das**2))
energy = np.sum(signal_das**2)
print(f"distance = {distance:10f}, sig_max = {np.max(signal_das):10f}, sig_min = {np.min(signal_das):10f}, rms = {rms:10f}, energy = {energy}")

and i got the result

image

@fakufaku
Copy link
Collaborator

fakufaku commented Apr 5, 2022

Hum, this looks pretty strange. I'm wondering if you may not be getting overflows due to using int16. Can you try doing the computations in floating point arithmetic ?

@shpark3312
Copy link
Author

I tried to divide the output signal in each case with same amount 2^16 (data type of output signal was float64) to prevent the overflow when getting the squar value and didn't convert to int16.

        room.mic_array.rake_perceptual_filters(room.sources[0][:2], None, R_n = sigma2_n * np.eye(mics.Lg * mics.M), delay = delay)
        signal_das = room.mic_array.process(FD=False)
        print(f'distance = {distance:10f}')
        print(f'Before converting to original output signal: max = {np.max(signal_das)}, min = {np.min(signal_das)}')
        
        # signal_das = np.array(signal_das/4, dtype=np.int16)
        signal_das = signal_das/2**16
        print(f'After dividing output signal by 2^16 : max = {np.max(signal_das)}, min = {np.min(signal_das)}')

        rms = np.sqrt(np.mean(signal_das**2))
        energy = np.sum(signal_das**2)

        print(f"sig_max = {np.max(signal_das):10f}, sig_min = {np.min(signal_das):10f}, rms = {rms:10f}, energy = {energy}\n")

but got result

image

and by the way thanks for the fast reply.

@fakufaku
Copy link
Collaborator

fakufaku commented Apr 6, 2022

I tried to write a test and I get nearly perfect decay by 1/d^2 for the energy.

import numpy as np
import pyroomacoustics as pra

if __name__ == "__main__":

    fs = 16000
    n = fs * 1
    x = np.random.randn(n)

    source = np.array([1.0, 1.0, 2.5])
    mics = np.array(
        [
            [1.0, 2.0, 2.5],
            [1.0, 11.0, 2.5],
            [1.0, 101.0, 2.5],
            [1.0, 1001.0, 2.5],
        ]
    )

    room = pra.ShoeBox([10000, 10000, 5], max_order=0, fs=fs)
    room.add_source(source, signal=x)
    for mic in mics:
        room.add_microphone(mic)
    room.simulate()

    signals = room.mic_array.signals

    energy = np.mean(signals ** 2, axis=-1)

    mic_1m = mics[0]
    energy_1m = energy[0]
    for idx in range(1, mics.shape[0]):
        dist = np.linalg.norm(mics[idx] - source)
        print(f"distance={dist:.3e} : energy decay = {energy_1m / energy[idx]:.3e}")

And the output of running the script is

> python test_energy.py
distance=1.000e+01 : energy decay = 1.004e+02
distance=1.000e+02 : energy decay = 9.976e+03
distance=1.000e+03 : energy decay = 9.922e+05

@shpark3312
Copy link
Author

With signal from single mic, I am getting the same result.
But with beamformed signal the decay is small.

I tried to make a rake_perceptual_filters - beamforming based on your code.

import numpy as np
import pyroomacoustics as pra

if __name__ == "__main__":

    fs = 16000
    fft_len = 1024
    Lg_t = 0.100
    sigma2_n = 5e-7
    Lg = np.ceil(Lg_t*fs)
    n = fs * 1
    x = np.random.randn(n)

    source = np.array([1.0, 1.0])
    centers = [
            [1.0, 2.0],
            [1.0, 11.0],
            [1.0, 101.0],
            [1.0, 1001.0],
        ]

    signals = []
    energys = []

    for center in centers:
        room = pra.ShoeBox([10000, 10000], max_order=0, fs=fs, sigma2_awgn=sigma2_n)
        room.add_source(source, signal=x)

        R = pra.circular_2D_array(center=center, M=12, phi0=0, radius=0.2)
        mics = pra.Beamformer(R, room.fs, N=fft_len, Lg=Lg)
        room.add_microphone_array(mics)
        room.simulate()

        room.mic_array.rake_perceptual_filters(room.sources[0][:2], None, sigma2_n * np.eye(mics.Lg * mics.M))
        result_signal = room.mic_array.process(FD=False)

        signals.append(result_signal)
        energys.append(np.mean(result_signal ** 2))


    mic_1m = centers[0]
    energy_1m = energys[0]

    for idx in range(1, len(centers)):
        dist = np.linalg.norm(centers[idx] - source)
        print(f"distance={dist:.3e} : energy decay = {energy_1m / energys[idx]:.3e}")

and the result was

distance=1.000e+01 : energy decay = 1.029e+00
distance=1.000e+02 : energy decay = 1.238e+00
distance=1.000e+03 : energy decay = 2.975e+00

@fakufaku
Copy link
Collaborator

fakufaku commented Apr 6, 2022

I would suggest to check out the code of the beamformer. I think it may be compensating for the amplitude. This would explain why you are not seeing much decay.
For an application without reverberation, and such long distance, I would suggest that you use a delay and sum beamformer. I don't think there is much merit to use the perceptual rake beamformer here. Rake beamformers use echoes, but in anechoic conditions there aren't any.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants