Commit fde10181 authored by Marek Szczerba's avatar Marek Szczerba
Browse files

Script update to generate acoustic environments metadata including early reflections

parent 5c40aeeb
Loading
Loading
Loading
Loading
+218 −7
Original line number Diff line number Diff line
@@ -196,10 +196,8 @@ def get_frequency_code(f):
def get_frequency_hop_code(index):
    assert 0 <= index < 9
    return [
        '1100',        # 2^(1/8)
        '1101',        # 2^(1/7)
        '0010',        # 2^(1/6)
        '0011',        # 2^(1/5)
        '0010',        # 2^(1/12)
        '0011',        # 2^(1/6)
        '0000',        # 2^(1/4)
        '01',          # 2^(1/3)
        '0001',        # 2^(1/2)
@@ -241,6 +239,93 @@ class fgdMethod(Enum):
    Default_Banding        = '10'


def get_distance_code(dist, isSmallScene = True):
    # 0, 1, ... 99
    metersCode = [
          '111101',   '110010',   '110011',   '110000',   '110001',   '110110',   '110111',   '110100',   '110101',   '001010',
          '001011',   '001000',   '001001',   '001110',   '001111',   '001100',   '001101',   '000010',   '000011',   '000000',
          '000001',   '000110',   '000111',   '000100',   '000101',   '011010',   '011011',   '011000',   '011001',   '011110',
          '011111',   '011100',   '011101',   '010010',   '010011',   '010000',   '010001',   '010110',   '010111',   '010100',
          '010101',   '101010',   '101011',   '101000',   '101001',   '101110',   '101111',   '101100',   '101101',    '10000',
         '1000100',  '1000101', '10001110', '10001111', '10001100', '10001101', '10011010', '10011011', '10011000', '10011001',
        '10011110', '10011111', '10011100', '10011101', '10010010', '10010011', '10010000', '10010001', '10010110', '10010111',
        '10010100', '10010101', '11101010', '11101011', '11101000', '11101001', '11101110', '11101111', '11101100', '11101101',
        '11100010', '11100011', '11100000', '11100001', '11100110', '11100111', '11100100', '11100101', '11111010', '11111011',
        '11111000', '11111001', '11111110', '11111111', '11111100', '11111101', '11110010', '11110011', '11110000', '11110001' ]

    # 0, 1, ... 9
    hectometersCode = [
          '000',   '001',   '110',   '111',   '100',   '101',  '0110',  '0111',  '0100',  '0101' ]

    # 1, 2, ... 10
    kilometersCode = [
           '10',   '011',   '001',   '000',   '111',  '0101',  '0100',  '1101', '11001', '11000' ]

    # 0, 1, ... 99
    centimetersCode = [
        '110010',   '110011',   '110000',   '110001',   '110110',   '110111',   '110100',   '110101',  '0101010',  '0101011',
       '0101000',  '0101001',  '0101110',  '0101111',  '0101100',  '0101101',  '0100010',  '0100011',  '0100000',  '0100001',
       '0100110',  '0100111',  '0100100',  '0100101',  '0111010',  '0111011',  '0111000',  '0111001',  '0111110',  '0111111',
       '0111100',  '0111101',  '0110010',  '0110011',  '0110000',  '0110001',  '0110110',  '0110111',  '0110100',  '0110101',
       '0001010',  '0001011',  '0001000',  '0001001',  '0001110',  '0001111',  '0001100',  '0001101',  '0000010',  '0000011',
       '0000000',  '0000001',  '0000110',  '0000111',  '0000100',  '0000101',  '0011010',  '0011011',  '0011000',  '0011001',
       '0011110',  '0011111',  '0011100',  '0011101',  '0010010',  '0010011',  '0010000',  '0010001',  '0010110',  '0010111',
       '0010100',  '0010101',   '101010',   '101011',   '101000',   '101001',   '101110',   '101111',   '101100',   '101101',
        '100010',   '100011',   '100000',   '100001',   '100110',   '100111',   '100100',   '100101',  '1111010',  '1111011',
       '1111000',  '1111001',  '1111110',  '1111111',  '1111100',  '1111101',   '111010',   '111011',   '111000',   '111001' ]

    distance_mm = int(round(np.float32(distance) * np.float32(1000)))      # distance in mm
    if print_cfg:
        print('distance: ', distance_mm)

    mm = distance_mm            # [mm]
    cm = mm // 10               # [cm]
    m = cm // 100               # [m]
    hm = m // 100               # [hm]
    km = hm // 10               # [km]

    mm = (mm % 10)              # 0, 1, ... 9  [mm]
    cm = (cm % 100)             # 0, 1, ... 99 [cm]
    m = (m % 100)               # 0, 1, ... 99 [m]
    hm = (hm % 9)               # 0, 1, ... 9  [hm]

    assert 0 <= mm <= 9
    assert 0 <= cm <= 99
    assert 0 <= m <= 99
    assert 0 <= hm <= 9
    assert distance_mm == km * 1000000 + hm * 100000 + m * 1000 + cm * 10 + mm

    code = metersCode[m]
    
    if not isSmallScene:
        # large scenes
        if hm > 0 or km > 0:
            # hectometers
            code += '1' + hectometersCode[hm]
            while km > 0:
                # kilometers
                code += '1' + kilometersCode[min(km, 10)]
                km = km - 10
            code += '0'
        else:
            code += '0'
    
    # centimeters
    if cm > 0:
        code += '1' + centimetersCode[cm]
    else:
        code += '0'

    return code


def get_absorption_code(absorption):
    assert 0.0 <= absorption <= 1.0

    index = round(absorption * 10.0)

    return ['110', '100', '101', '0110', '0111', '111', '0100', '0101', '0010', '0011', '000' ][index]

# apply function to elements of list and concatenate the resulting strings
def concatenate(function, data):
    return ''.join([function(d) for d in data])
@@ -248,6 +333,7 @@ def concatenate(function, data):

def test():
    # generate binary output which can be compared with the Matlab implementation output
    
    string = ''

    # count or index encoding
@@ -282,7 +368,54 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg():
    # based on config_renderer.cfg
    # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values
    data = bitarray(
          get_count_or_index_code(1)              # fgdNrGrids
        '1'                                       # hasAcEnv
        + get_count_or_index_code(1)              # fgdNrGrids
        + fgdMethod.Individual_Frequencies.value  #   fgdMethod
        + get_count_or_index_code(31)             #     fgdNrBands

        + concatenate(get_frequency_code,         #       fgdCenterFreq
            [    20.0,   25.0,   31.5,   40.0,   50.0,   63.0,   80.0,   100.0,   125.0,   160.0,
                200.0,  250.0,  315.0,  400.0,  500.0,  630.0,  800.0,  1000.0,  1250.0,  1600.0,
               2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, 12500.0, 16000.0,
              20000.0 ])
                                            
        + get_count_or_index_code(1)              # AcousticEnvCount
        + get_id_code(0)                          #   ID
        + get_count_or_index_code(0)              #   FreqGridID
        + get_duration_code(0.1)                  #   (input)Predelay

        + concatenate(get_duration_code,          #     RT60
            [ 1.3622, 1.4486, 1.3168, 1.5787, 1.4766,  1.3954,  1.2889,  1.3462,  1.0759,  1.0401,
              1.0970, 1.0850, 1.0910, 1.0404, 1.0499,  1.0699,  1.1028,  1.1714,  1.1027,  1.0666,
              1.0550, 1.0553, 1.0521, 1.0569, 1.0421, 0.97822, 0.80487, 0.75944, 0.71945, 0.61682,
              0.60031 ])

        + concatenate(get_dsr_code,               #     DSR
            [ 1.8811e-08, 2.1428e-08, 1.3972e-08,   1.51e-08,  1.287e-08, 1.8747e-08,  2.413e-08, 3.9927e-08, 8.9719e-08,  1.902e-07,
               3.702e-07, 6.1341e-07, 7.1432e-07, 6.5331e-07, 4.6094e-07, 5.4683e-07, 7.0134e-07,  6.856e-07,  7.114e-07, 6.9604e-07,
              5.2939e-07,  5.699e-07, 6.1773e-07, 5.7488e-07, 4.7748e-07, 2.7213e-07, 1.3681e-07, 1.0941e-07, 6.2001e-08, 2.8483e-08,
              2.6267e-08 ])
        + '0'                                     #   hasEarlyReflections
        , endian='big')

    file = open('rend_config_renderer.dat', 'wb')
    data.tofile(file)
    file.close()

def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_no_listener_origin():
    # based on config_renderer.cfg
    # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values
    data = bitarray(
        '1'                                       # hasAcEnv
        + get_count_or_index_code(2)              # fgdNrGrids
        # frequency grid #1
        + fgdMethod.Individual_Frequencies.value  #   fgdMethod
        + get_count_or_index_code(1)              #     fgdNrBands

        + concatenate(get_frequency_code,         #       fgdCenterFreq
            [ 10000.0 ])

        # frequency grid #2    
        + fgdMethod.Individual_Frequencies.value  #   fgdMethod
        + get_count_or_index_code(31)             #     fgdNrBands

@@ -294,7 +427,64 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg():
                                            
        + get_count_or_index_code(1)              # AcousticEnvCount
        + get_id_code(0)                          #   ID
        + get_count_or_index_code(1)              #   FreqGridID
        + get_duration_code(0.1)                  #   (input)Predelay

        + concatenate(get_duration_code,          #     RT60
            [ 1.3622, 1.4486, 1.3168, 1.5787, 1.4766,  1.3954,  1.2889,  1.3462,  1.0759,  1.0401,
              1.0970, 1.0850, 1.0910, 1.0404, 1.0499,  1.0699,  1.1028,  1.1714,  1.1027,  1.0666,
              1.0550, 1.0553, 1.0521, 1.0569, 1.0421, 0.97822, 0.80487, 0.75944, 0.71945, 0.61682,
              0.60031 ])

        + concatenate(get_dsr_code,               #     DSR
            [ 1.8811e-08, 2.1428e-08, 1.3972e-08,   1.51e-08,  1.287e-08, 1.8747e-08,  2.413e-08, 3.9927e-08, 8.9719e-08,  1.902e-07,
               3.702e-07, 6.1341e-07, 7.1432e-07, 6.5331e-07, 4.6094e-07, 5.4683e-07, 7.0134e-07,  6.856e-07,  7.114e-07, 6.9604e-07,
              5.2939e-07,  5.699e-07, 6.1773e-07, 5.7488e-07, 4.7748e-07, 2.7213e-07, 1.3681e-07, 1.0941e-07, 6.2001e-08, 2.8483e-08,
              2.6267e-08 ])

        + '1'                                     #   hasEarlyReflections
        + concatenate(get_distance_code,          #     room dimensions
            [ 3.0, 4.0, 2.5 ])
        
        + get_count_or_index_code(0)              #     FreqGridID
        + concatenate(get_absorption_code,        #     absorptionCode
            [ 0.8, 0.8, 0.8, 0.8, 0.2, 0.6 ])

        + '0'                                     #     listener origin flag

        , endian='big')

    file = open('rend_config_renderer.dat', 'wb')
    data.tofile(file)
    file.close()


def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_listener_origin():
    # based on config_renderer.cfg
    # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values
    data = bitarray(
        '1'                                       # hasAcEnv
        + get_count_or_index_code(2)              # fgdNrGrids
        # frequency grid #1
        + fgdMethod.Individual_Frequencies.value  #   fgdMethod
        + get_count_or_index_code(1)              #     fgdNrBands

        + concatenate(get_frequency_code,         #       fgdCenterFreq
            [ 10000.0 ])

        # frequency grid #2    
        + fgdMethod.Individual_Frequencies.value  #   fgdMethod
        + get_count_or_index_code(31)             #     fgdNrBands

        + concatenate(get_frequency_code,         #       fgdCenterFreq
            [    20.0,   25.0,   31.5,   40.0,   50.0,   63.0,   80.0,   100.0,   125.0,   160.0,
                200.0,  250.0,  315.0,  400.0,  500.0,  630.0,  800.0,  1000.0,  1250.0,  1600.0,
               2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, 12500.0, 16000.0,
              20000.0 ])
                                            
        + get_count_or_index_code(1)              # AcousticEnvCount
        + get_id_code(0)                          #   ID
        + get_count_or_index_code(1)              #   FreqGridID
        + get_duration_code(0.1)                  #   (input)Predelay

        + concatenate(get_duration_code,          #     RT60
@@ -309,6 +499,20 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg():
              5.2939e-07,  5.699e-07, 6.1773e-07, 5.7488e-07, 4.7748e-07, 2.7213e-07, 1.3681e-07, 1.0941e-07, 6.2001e-08, 2.8483e-08,
              2.6267e-08 ])

        + '1'                                     #   hasEarlyReflections
        + concatenate(get_distance_code,          #     room dimensions
            [ 3.0, 4.0, 2.5 ])
        
        + get_count_or_index_code(0)              #     FreqGridID
        + concatenate(get_absorption_code,        #     absorptionCode
            [ 0.8, 0.8, 0.8, 0.8, 0.2, 0.6 ])

        + '1'                                     #     listener origin flag
        + '1'                                     #     positive x origin
        + '0'                                     #     negative y origin
        + concatenate(get_distance_code,          #     listener origin (x, y, z)
            [ 0.5, 0.5, 1.5 ])

        , endian='big')

    file = open('rend_config_renderer.dat', 'wb')
@@ -316,11 +520,13 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg():
    file.close()



def generate_reverb_payload_equivalent_to_rend_config_hospital_patientroom_cfg():
    # based on config_hospital_patientroom.cfg
    # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values
    data = bitarray(
          get_count_or_index_code(1)              # fgdNrGrids
        1                                         # hasAcEnv
        + get_count_or_index_code(1)              # fgdNrGrids
        + fgdMethod.Individual_Frequencies.value  #   fgdMethod
        + get_count_or_index_code(31)             #     fgdNrBands

@@ -348,6 +554,8 @@ def generate_reverb_payload_equivalent_to_rend_config_hospital_patientroom_cfg()
                6.379496e-06,   6.358105e-06,    6.6696e-06,  6.369334e-06, 6.378474e-06, 3.339913e-06, 3.129318e-06, 2.892564e-06,   6.00202e-07,  3.40124e-07,
                 3.37705e-07 ])

        + '0'                                     #   hasEarlyReflections

        , endian='big')

    file = open('rend_config_hospital_patientroom.dat', 'wb')
@@ -359,7 +567,8 @@ def generate_reverb_payload_equivalent_to_rend_config_recreation_cfg():
    # based on config_recreation.cfg
    # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values
    data = bitarray(
          get_count_or_index_code(1)              # fgdNrGrids
        1                                         # hasAcEnv
        + get_count_or_index_code(1)              # fgdNrGrids
        + fgdMethod.Individual_Frequencies.value  #   fgdMethod
        + get_count_or_index_code(31)             #     fgdNrBands

@@ -387,6 +596,8 @@ def generate_reverb_payload_equivalent_to_rend_config_recreation_cfg():
              2.958383e-06, 2.725911e-06,  7.94912e-07,  6.20198e-07,  5.71181e-07,   5.5546e-08,   1.3987e-08,    1.338e-08,    1.322e-09,      1.3e-11,
                     4e-12 ])

        + '0'                                     #   hasEarlyReflections

        , endian='big')

    file = open('rend_config_recreation.dat', 'wb')