Example #1
0
def compute_array(meshpath, src_coord, lis_coord, r, s, micarray):
    mesh = ps.loadobj(meshpath, os.path.join(os.path.dirname(meshpath), ''), r, s)
    ctx = ps.Context()
    ctx.diffuse_count = 20000
    ctx.specular_count = 2000
    ctx.channel_type = ps.ChannelLayoutType.mono
    scene = ps.Scene()
    scene.setMesh(mesh)

    src = ps.Source(src_coord)
    src.radius = 0.01

    res = {}
    res_buffer = []
    rate = 0
    abandon_flag = False
    for offset in micarray:
        lis = ps.Listener((offset + lis_coord).tolist())
        lis.radius = 0.01

        res_ch = scene.computeIR(src, lis, ctx)
        rate = res_ch['rate']
        sa = res_ch['samples']
        res['rate'] = rate
        res_buffer.append(sa)
    res['samples'] = np.zeros((len(res_buffer), np.max([len(ps) for ps in res_buffer])))
    for i, c in enumerate(res_buffer):
        res['samples'][i, :len(c)] = c
    return res
Example #2
0
def main():
    # Simulation using .obj file (and an optional .mtl file)
    ctx = ps.Context()
    ctx.diffuse_count = 20000
    ctx.specular_count = 2000
    ctx.channel_type = ps.ChannelLayoutType.stereo

    mesh1 = ps.loadobj(
        "cube.obj", ""
    )  # if the second argument is empty, the code will infer the .mtl name using .obj name
    scene = ps.Scene()
    scene.setMesh(mesh1)

    src_coord = [1, 1, 0.5]
    lis_coord = [5, 3, 0.5]

    src = ps.Source(src_coord)
    src.radius = 0.01

    lis = ps.Listener(lis_coord)
    lis.radius = 0.01

    res = scene.computeMultichannelIR(src, lis, ctx)

    w = WaveWriter('test1.wav',
                   channels=np.shape(res['samples'])[0],
                   samplerate=int(res['rate']))
    w.write(np.array(res['samples']))
    print("IR using .obj input written to test1.wav.")

    # Simulation using a shoebox definition
    ctx = ps.Context()
    ctx.diffuse_count = 20000
    ctx.specular_count = 2000
    ctx.channel_type = ps.ChannelLayoutType.stereo

    mesh2 = ps.createbox(10, 6, 2, 0.5, 0.5)
    scene = ps.Scene()
    scene.setMesh(mesh2)

    res = scene.computeMultichannelIR(src, lis, ctx)
    w2 = WaveWriter('test2.wav',
                    channels=np.shape(res['samples'])[0],
                    samplerate=int(res['rate']))
    w2.write(np.array(res['samples']))
    print("IR using shoebox input written to test2.wav.")
Example #3
0
def compute_scene_ir_absorb(roomdim, tasks, r):
    # Initialize scene mesh
    try:
        mesh = ps.createbox(roomdim[0], roomdim[1], roomdim[2], r, 0.5)
    except Exception as e:
        print(str(e))

    ctx = ps.Context()
    ctx.diffuse_count = 2000
    ctx.specular_count = 2000
    ctx.threads_count = min(multiprocessing.cpu_count(), 8)

    scene = ps.Scene()
    scene.setMesh(mesh)

    channel = ps.ChannelLayoutType.mono
    ctx.channel_type = channel
    ctx.sample_rate = 16000

    status = 0

    for task in tasks:
        src_coord = task[0]
        lis_coord = task[1]
        wavname = task[2]

        cnt = 0
        src = ps.Source(src_coord)
        src.radius = 0.01

        lis = ps.Listener(lis_coord)
        lis.radius = 0.01
        # lis.channel_layout_type = ps.ChannelLayoutType.mono

        a = np.array(src_coord)
        b = np.array(lis_coord)
        dist = np.linalg.norm(a - b)
        direct_idx = int(ctx.sample_rate * dist / 343)
        res = scene.computeIR(src, lis, ctx)
        res['samples'] = np.atleast_2d(res['samples'])
        if (np.argmax(np.fabs(res['samples'])) == 0):
            status = 1
            wavname += '_startzero.wav'
        elif (np.max(np.fabs(res['samples'])) == 0):
            status = 2
            wavname += '_zeromax.wav'
        elif (np.isnan(res['samples']).any()):
            status = 3
            wavname += '_nan.wav'

    return status
Example #4
0
def main():
    l = 10
    w = 6
    h = 2
    absorb = 0.3
    reflec = np.sqrt(1.0 - absorb)

    ctx = ps.Context()
    ctx.diffuse_count = 20000
    ctx.specular_count = 2000
    ctx.channel_type = ps.ChannelLayoutType.mono
    scene = ps.Scene()

    mesh = ps.createbox(l, w, h, absorb, 0.5)
    scene.setMesh(mesh)

    src_coord = [1, 1, 0.5]
    lis_coord = [5, 3, 0.5]

    src = ps.Source(src_coord)
    src.radius = 0.01

    lis = ps.Listener(lis_coord)
    lis.radius = 0.01

    rir_gs = scene.computeIR(src, lis, ctx)
    rir_img = rg.rir_generator(343,
                               16000,
                               lis_coord,
                               src_coord, [l, w, h],
                               beta=[reflec] * 6)
    rir_img = rir_img / max(abs(rir_img[0]))

    max_cnt = min(len(rir_gs['samples']), len(rir_img[0])) * 2

    fig, axs = plt.subplots(4, 1, figsize=(10, 20))
    axs[0].set_title('Image Method (waveform)')
    axs[0].plot(rir_img[0], linewidth=0.5)
    axs[0].set_xlabel('Sample')
    axs[0].set_xlim(0, max_cnt)
    axs[0].set_ylim(-1, 1)
    axs[0].set_ylabel('Amplitude')

    axs[1].set_title('Geometric Sound Propagation (waveform)')
    axs[1].plot(rir_gs['samples'], linewidth=0.5)
    axs[1].set_xlabel('Sample')
    axs[1].set_xlim(0, max_cnt)
    axs[1].set_ylim(-1, 1)
    axs[1].set_ylabel('Amplitude')

    axs[2].set_title('Image Method (spectrogram)')
    axs[2].specgram(rir_img[0],
                    mode='magnitude',
                    NFFT=1024,
                    Fs=16000,
                    noverlap=512)
    axs[2].set_xlim(0, max_cnt / 16000)
    axs[2].set_xlabel('Times (s)')
    axs[2].set_ylabel('Frequency (Hz)')

    axs[3].set_title('Geometric Sound Propagation (spectrogram)')
    axs[3].specgram(rir_gs['samples'],
                    mode='magnitude',
                    NFFT=1024,
                    Fs=16000,
                    noverlap=512)
    axs[3].set_xlim(0, max_cnt / 16000)
    axs[3].set_xlabel('Times (s)')
    axs[3].set_ylabel('Frequency (Hz)')

    fig.tight_layout()
    plt.savefig('img_comparison.png')
    plt.show()
Example #5
0
def compute_room_irs(
    room_dim,
    mic_pos,
    source_pos,
    ray_tracing=False,
    room_properties=0.5,
    sample_rate=16000,
    ism_order=None,
    air_absorption=False,
    ray_tracing_param=None,
    scattering=0.5,
    temperature=None,
    software=RoomSimSoftware.PYROOMACOUSTICS,
):
    """

    Compute the RIRs between a provided mic position and one or multiple
    source position(s). Default is to apply Image Source Method (ISM) with
    order 17.

    Parameters
    ----------
    room_dim : array or list
        3D array, specifying (width, length, height) or a Shoebox room.
    mic_pos : array or list
        3D array specifying coordinates of microphone.
    source_pos : list of arrays
        List of coordinates for source positions.
    ray_tracing : bool
        Whether to apply ray tracing.
    room_properties : float or dict, optional
        If float, average RT60 of the room from which the average absorption is
        determined using Eyring's equation. If dict, one entry per wall in
        `WallRegistry` for the corresponding material.
    sample_rate : int, optional
        Sample rate in Hz.
    ism_order : int, optional
        Number of specular reflections to model with ISM.
    air_absorption : bool
        Whether to include air absorption in the simulation.
    ray_tracing_param : dict, optional
        Dict of parameters for ray tracing.
    scattering : float, optional
        Average scattering coefficient for all surfaces and frequencies.
    temperature : float, optional
        Temperature in Celsius.
    software : str, optional
        Which simulation software to use. "pyroomacoustics" (default) or
        "pygsound".
    """

    # check input parameters
    assert len(room_dim) == 3
    assert len(mic_pos) == 3
    mic_pos = np.array(mic_pos, ndmin=2).T
    for _pos in source_pos:
        assert len(_pos) == 3

    # prepare parameters
    energy_absorption = None
    scattering_config = {
        "description": "Flat scattering",
        "coeffs": [scattering],
    }
    if isinstance(room_properties, dict):
        materials_config = dict()
        for wall in room_properties:
            materials_config[wall] = pra.Material(
                energy_absorption=materials_absorption_table[
                    room_properties[wall]
                ],
                scattering=scattering_config,
            )
    elif isinstance(room_properties, float):
        energy_absorption = rt60_to_absorption(
            room_dim=room_dim, rt60=room_properties
        )
        materials_config = pra.Material(
            energy_absorption=energy_absorption, scattering=scattering_config
        )
    else:
        raise ValueError(
            "Invalid `materials`, must be `dict` with an entry"
            " for each wall or a `float` for an RT60."
        )

    # build room and simulate
    if software == RoomSimSoftware.PYROOMACOUSTICS:

        if ism_order is None:
            ism_order = 17

        pyroomacoustics_rt_param = {
            "n_rays": int(1e5),
            "receiver_radius": 0.5,
            "time_thres": 10.0,
        }
        if ray_tracing_param is not None:
            pyroomacoustics_rt_param.update(ray_tracing_param)

        room = pra.room.ShoeBox(
            p=room_dim,
            fs=sample_rate,
            materials=materials_config,
            max_order=ism_order,
            mics=pra.MicrophoneArray(mic_pos, sample_rate),
            air_absorption=air_absorption,
            ray_tracing=ray_tracing,
            temperature=temperature,
            humidity=0 if temperature is not None else None,
        )
        if ray_tracing:
            room.set_ray_tracing(**pyroomacoustics_rt_param)

        # add sources
        for _source_loc in source_pos:
            room.add_source(list(_source_loc))

        # compute RIRs
        room.compute_rir()
        rirs = room.rir[0]

    elif software == RoomSimSoftware.PYGSOUND:

        assert energy_absorption is not None
        assert isinstance(
            room_properties, float
        ), "`room_property` must be an RT60 value for `pygsound`"
        if air_absorption:
            print("Air absorption not available for `pygsound`.")
        if ism_order is not None:
            print("ISM order cannot be set for `pygsound`.")
        pygsound_param = {
            "diffuse_count": 20000,
            "specular_count": 2000,
            "src_radius": 0.01,
            "mic_radius": 0.01,
        }
        if ray_tracing_param is not None:
            pygsound_param.update(ray_tracing_param)

        # simulation variables
        ctx = ps.Context()
        ctx.diffuse_count = pygsound_param["diffuse_count"]
        ctx.specular_count = pygsound_param["specular_count"]
        if "specular_depth" in pygsound_param:
            ctx.specular_depth = pygsound_param["specular_depth"]
        ctx.channel_type = ps.ChannelLayoutType.mono
        ctx.sample_rate = sample_rate

        # create ShoeBox room
        mesh2 = ps.createbox(
            _width=room_dim[0],
            _length=room_dim[1],
            _height=room_dim[2],
            _absorp=energy_absorption,
            _scatter=scattering,
        )
        scene = ps.Scene()
        scene.setMesh(mesh2)

        # compute RIRs
        rirs = []
        for _pos in source_pos:
            _rir = pygsound_compute_ir(
                scene=scene,
                context=ctx,
                source_pos=_pos,
                mic_pos=mic_pos,
                src_radius=pygsound_param["src_radius"],
                mic_radius=pygsound_param["mic_radius"],
            )
            rirs.append(_rir)

    else:
        raise ValueError("Invalid simulation software.")

    return rirs, sample_rate