listeningpy.set_preparation

Functions for preparing sets for listening tests.

  1"""
  2Functions for preparing sets for listening tests.
  3"""
  4
  5from pandas import DataFrame, concat
  6import logging
  7from itertools import combinations
  8import os
  9# logging.basicConfig(level=logging.INFO)
 10
 11### GENERAL ###
 12
 13def filter_wavs(paths: list[str]) -> list[str]:
 14    '''Filters files with '.wav' extension from a list of paths.
 15
 16    Parameters
 17    ----------
 18    paths : list[str]
 19        list of file paths
 20
 21    Returns
 22    -------
 23    paths : list[str]
 24        list of filtered file paths
 25    '''
 26    paths = filter(lambda file: file.lower().endswith('.wav'), paths)
 27    return list(paths)
 28
 29def read_folder(
 30        folder,
 31        parent=None,
 32        filterwav=True
 33        ) -> list[str]:
 34    '''Reads files inside a specified folder and keeps '.wav' files
 35    inside it. 
 36
 37    Parameters
 38    ----------
 39    folder : str
 40        folder containing wav files
 41    parent : str
 42        path to project folder
 43    filterwav : bool
 44        True value filters out other than '.wav' files
 45
 46    Returns
 47    -------
 48    audio_paths : list[str]
 49        list containing paths to audio files inside a specified folder
 50    '''
 51    if parent == None:
 52        audio_folder = folder
 53    else:
 54        audio_folder = os.path.join(parent, folder)
 55    audio_paths = os.scandir(audio_folder)
 56    audio_paths = [
 57        os.path.join(audio_folder, p.name) for p in audio_paths if p.is_file()
 58        ]
 59    if filterwav:
 60        audio_paths = filter_wavs(audio_paths)
 61    logging.info(f"Read these files: {audio_paths}")
 62    return audio_paths
 63
 64def sub_folders(
 65        folder : str,
 66        ) -> list[str]:
 67    """Return a list of sub-folders within the specified folder.
 68
 69    Parameters
 70    ----------
 71    folder : str
 72        The name of the folder.
 73    parent : str
 74        The parent directory of the folder.
 75
 76    Returns
 77    -------
 78    list[str]
 79        A list of sub-folders within the specified folder.
 80    """
 81    parent = os.path.split(folder)[0]
 82    main_folder = os.path.join(parent, folder)
 83    subs = os.scandir(main_folder)
 84    subs = [
 85        os.path.join(parent, folder, p.name)
 86        for p in subs if p.is_dir()
 87        ]
 88    return subs
 89
 90def randomization(df: DataFrame) -> DataFrame:
 91    '''
 92    Shuffles rows in a provided DataFrame. In this context, it randomizes
 93    sets for discrimination listening tests.
 94
 95    Parameters
 96    ----------
 97    df : pandas.DataFrame
 98        DataFrame containing sets for the listening test, one per row.
 99
100    Returns
101    -------
102    df : pandas.DataFrame
103        DataFrame with randomly shuffled rows.
104    '''
105    return df.sample(frac=1).reset_index(drop=True)
106
107### COMBINATIONS PREPARATION ###
108
109def abx_combination(
110        folder: str,
111        parent: str=".",
112        constant_reference: bool=False
113        ) -> DataFrame:
114    '''Reads files in a specified folder and generates combinations for
115    ABX test.
116
117    Parameters
118    ----------
119    folder : str
120        Folder containing wav files.
121    parent : str, optional
122        Path to the project folder. Default is the current directory.
123    constant_reference : bool, optional
124        Determines whether to generate combinations for standard ABX (False) or CR-ABX (True).
125        For CR-ABX, the combinations will have half the length of ABX. Default is False.
126
127    Returns
128    -------
129    audio_path_comb : pandas.DataFrame
130        Sorted sets for ABX test.
131
132    Notes
133    -----
134    - The function reads the files in the specified folder and generates combinations of pairs.
135    - Each combination is represented as a row in the returned DataFrame.
136    - The DataFrame contains columns for the two audio paths in each combination, as well as an ID column.
137    - If constant_reference is True, the reference audio path will be the same for all combinations.
138      Otherwise, the reference audio path will vary for each combination.
139    - The DataFrame is sorted by the first audio path in each combination.
140
141    Examples
142    --------
143    >>> abx_combination("audio_folder", parent="project_folder", constant_reference=True)
144    Returns combinations for CR-ABX with a constant reference audio path.
145
146    >>> abx_combination("audio_folder")
147    Returns combinations for standard ABX.
148
149    '''
150    audio_path_list = read_folder(folder, parent)
151    audio_path_comb = DataFrame(combinations(audio_path_list, 2), columns=['0', '1'])
152    audio_path_comb['ID'] = audio_path_comb.index.format(name=False, formatter="{0:0=2d}".format)
153    if constant_reference:
154        audio_path_comb["Ref"] = audio_path_comb.loc[:, '0']
155    else:
156        audio_path_comb_copy = audio_path_comb.copy()
157        audio_path_comb["Ref"] = audio_path_comb.loc[:, '0']
158        audio_path_comb_copy["Ref"] = audio_path_comb_copy.loc[:, '1']
159        audio_path_comb = concat([audio_path_comb, audio_path_comb_copy])
160        
161    audio_path_comb_inv = audio_path_comb.copy()
162    audio_path_comb_inv.loc[:, ['1', '0']] = audio_path_comb_inv.loc[:, ['0', '1']].values
163    audio_path_comb = concat([audio_path_comb, audio_path_comb_inv]).reset_index(drop=True)
164    audio_path_comb = audio_path_comb.sort_values(by=['0'])
165    logging.info("ABX combinations returned.")
166    return audio_path_comb
167
168def abx_combination_subset(
169        folder: str,
170        parent: str=".",
171        constant_reference: bool=False
172        ) -> DataFrame:
173    '''Reads files in a specified folder and generates combinations for
174    ABX test. Creates a subset of combinations containing the first path
175    read.
176
177    Parameters
178    ----------
179    folder : str
180        Folder containing wav files.
181    parent : str, optional
182        Path to the project folder. Default is the current directory.
183    constant_reference : bool, optional
184        Determines whether to return combinations for standard ABX (False)
185        or CR-ABX (True) with half the length of ABX. Default is False.
186
187    Returns
188    -------
189    audio_path_comb : pandas.DataFrame
190        Sorted sets for ABX test.
191
192    Notes
193    -----
194    This function reads the files in the specified folder and generates
195    combinations for an ABX test. It creates a subset of combinations
196    that contain the first path read. The resulting combinations are
197    returned as a pandas DataFrame.
198
199    If `constant_reference` is True, the function generates combinations
200    for CR-ABX, where the reference path remains constant. If False, it
201    generates combinations for standard ABX, where the reference path
202    changes for each combination.
203
204    Examples
205    --------
206    >>> abx_combination_subset("audio_folder", parent="project_folder", constant_reference=True)
207    Returns combinations for CR-ABX with the first path as the reference.
208
209    >>> abx_combination_subset("audio_folder", constant_reference=False)
210    Returns combinations for standard ABX with the first path as the reference.
211    '''
212    audio_path_list = read_folder(folder, parent)
213    audio_path_comb = DataFrame(combinations(audio_path_list, 2), columns=['0', '1'])
214    audio_path_comb = audio_path_comb[audio_path_comb.loc[:,'0'] == audio_path_list[0]]
215    audio_path_comb['ID'] = audio_path_comb.index.format(name=False, formatter="{0:0=2d}".format)
216    if constant_reference:
217        audio_path_comb["Ref"] = audio_path_comb.loc[:, '0']
218    else:
219        audio_path_comb_copy = audio_path_comb.copy()
220        audio_path_comb["Ref"] = audio_path_comb.loc[:, '0']
221        audio_path_comb_copy["Ref"] = audio_path_comb_copy.loc[:, '1']
222        audio_path_comb = concat([audio_path_comb, audio_path_comb_copy])
223        
224    audio_path_comb_inv = audio_path_comb.copy()
225    audio_path_comb_inv.loc[:, ['0', '1']] = audio_path_comb_inv.loc[:, ['0', '1']].values
226    audio_path_comb = concat([audio_path_comb, audio_path_comb_inv]).reset_index(drop=True)
227    audio_path_comb = audio_path_comb.sort_values(by=['0'])
228    logging.info("ABX combinations returned.")
229    return audio_path_comb
230
231def adaptive_combination(folder: str, parent: str):
232    '''Reads files in a specified folder and generates combinations for
233    adaptive method test.
234
235    Parameters
236    ----------
237    folder : str
238        Folder containing set subfolders.
239    parent : str
240        Path to project folder.
241
242    Returns
243    -------
244    audio_path_df : pandas.DataFrame
245        Sorted sets for adaptive method test.
246    '''
247    audio_path_df = DataFrame()
248    sets = sub_folders(folder, parent)
249    for s in sets:
250        paths = read_folder(s)
251        ids = [os.path.split(p)[1][:-4] for p in paths]
252        set_list = [os.path.split(s)[1] for p in paths]
253        dict_ = {'set': set_list, 'id': ids, 'path':paths}
254        df = DataFrame(dict_)
255        audio_path_df = concat([audio_path_df, df])
256    return audio_path_df
257
258def adaptive_irs(folder: str):
259    '''Reads files in a specified folder and generates DataFrame
260
261    Parameters
262    ----------
263    folder : str
264        folder containing set subfolders
265
266    Returns
267    -------
268    audio_path_df : pandas.DataFrame
269        sorted irs for adaptive method test
270    '''
271    paths = read_folder(folder)
272    paths.sort()
273    ids = [os.path.split(p)[1][:-4] for p in paths]
274    dict_ = {'id': ids, 'path':paths}
275    audio_path_df = DataFrame(dict_)
276    
277    return audio_path_df
def filter_wavs(paths: list[str]) -> list[str]:
14def filter_wavs(paths: list[str]) -> list[str]:
15    '''Filters files with '.wav' extension from a list of paths.
16
17    Parameters
18    ----------
19    paths : list[str]
20        list of file paths
21
22    Returns
23    -------
24    paths : list[str]
25        list of filtered file paths
26    '''
27    paths = filter(lambda file: file.lower().endswith('.wav'), paths)
28    return list(paths)

Filters files with '.wav' extension from a list of paths.

Parameters
  • paths (list[str]): list of file paths
Returns
  • paths (list[str]): list of filtered file paths
def read_folder(folder, parent=None, filterwav=True) -> list[str]:
30def read_folder(
31        folder,
32        parent=None,
33        filterwav=True
34        ) -> list[str]:
35    '''Reads files inside a specified folder and keeps '.wav' files
36    inside it. 
37
38    Parameters
39    ----------
40    folder : str
41        folder containing wav files
42    parent : str
43        path to project folder
44    filterwav : bool
45        True value filters out other than '.wav' files
46
47    Returns
48    -------
49    audio_paths : list[str]
50        list containing paths to audio files inside a specified folder
51    '''
52    if parent == None:
53        audio_folder = folder
54    else:
55        audio_folder = os.path.join(parent, folder)
56    audio_paths = os.scandir(audio_folder)
57    audio_paths = [
58        os.path.join(audio_folder, p.name) for p in audio_paths if p.is_file()
59        ]
60    if filterwav:
61        audio_paths = filter_wavs(audio_paths)
62    logging.info(f"Read these files: {audio_paths}")
63    return audio_paths

Reads files inside a specified folder and keeps '.wav' files inside it.

Parameters
  • folder (str): folder containing wav files
  • parent (str): path to project folder
  • filterwav (bool): True value filters out other than '.wav' files
Returns
  • audio_paths (list[str]): list containing paths to audio files inside a specified folder
def sub_folders(folder: str) -> list[str]:
65def sub_folders(
66        folder : str,
67        ) -> list[str]:
68    """Return a list of sub-folders within the specified folder.
69
70    Parameters
71    ----------
72    folder : str
73        The name of the folder.
74    parent : str
75        The parent directory of the folder.
76
77    Returns
78    -------
79    list[str]
80        A list of sub-folders within the specified folder.
81    """
82    parent = os.path.split(folder)[0]
83    main_folder = os.path.join(parent, folder)
84    subs = os.scandir(main_folder)
85    subs = [
86        os.path.join(parent, folder, p.name)
87        for p in subs if p.is_dir()
88        ]
89    return subs

Return a list of sub-folders within the specified folder.

Parameters
  • folder (str): The name of the folder.
  • parent (str): The parent directory of the folder.
Returns
  • list[str]: A list of sub-folders within the specified folder.
def randomization(df: pandas.core.frame.DataFrame) -> pandas.core.frame.DataFrame:
 91def randomization(df: DataFrame) -> DataFrame:
 92    '''
 93    Shuffles rows in a provided DataFrame. In this context, it randomizes
 94    sets for discrimination listening tests.
 95
 96    Parameters
 97    ----------
 98    df : pandas.DataFrame
 99        DataFrame containing sets for the listening test, one per row.
100
101    Returns
102    -------
103    df : pandas.DataFrame
104        DataFrame with randomly shuffled rows.
105    '''
106    return df.sample(frac=1).reset_index(drop=True)

Shuffles rows in a provided DataFrame. In this context, it randomizes sets for discrimination listening tests.

Parameters
  • df (pandas.DataFrame): DataFrame containing sets for the listening test, one per row.
Returns
  • df (pandas.DataFrame): DataFrame with randomly shuffled rows.
def abx_combination( folder: str, parent: str = '.', constant_reference: bool = False) -> pandas.core.frame.DataFrame:
110def abx_combination(
111        folder: str,
112        parent: str=".",
113        constant_reference: bool=False
114        ) -> DataFrame:
115    '''Reads files in a specified folder and generates combinations for
116    ABX test.
117
118    Parameters
119    ----------
120    folder : str
121        Folder containing wav files.
122    parent : str, optional
123        Path to the project folder. Default is the current directory.
124    constant_reference : bool, optional
125        Determines whether to generate combinations for standard ABX (False) or CR-ABX (True).
126        For CR-ABX, the combinations will have half the length of ABX. Default is False.
127
128    Returns
129    -------
130    audio_path_comb : pandas.DataFrame
131        Sorted sets for ABX test.
132
133    Notes
134    -----
135    - The function reads the files in the specified folder and generates combinations of pairs.
136    - Each combination is represented as a row in the returned DataFrame.
137    - The DataFrame contains columns for the two audio paths in each combination, as well as an ID column.
138    - If constant_reference is True, the reference audio path will be the same for all combinations.
139      Otherwise, the reference audio path will vary for each combination.
140    - The DataFrame is sorted by the first audio path in each combination.
141
142    Examples
143    --------
144    >>> abx_combination("audio_folder", parent="project_folder", constant_reference=True)
145    Returns combinations for CR-ABX with a constant reference audio path.
146
147    >>> abx_combination("audio_folder")
148    Returns combinations for standard ABX.
149
150    '''
151    audio_path_list = read_folder(folder, parent)
152    audio_path_comb = DataFrame(combinations(audio_path_list, 2), columns=['0', '1'])
153    audio_path_comb['ID'] = audio_path_comb.index.format(name=False, formatter="{0:0=2d}".format)
154    if constant_reference:
155        audio_path_comb["Ref"] = audio_path_comb.loc[:, '0']
156    else:
157        audio_path_comb_copy = audio_path_comb.copy()
158        audio_path_comb["Ref"] = audio_path_comb.loc[:, '0']
159        audio_path_comb_copy["Ref"] = audio_path_comb_copy.loc[:, '1']
160        audio_path_comb = concat([audio_path_comb, audio_path_comb_copy])
161        
162    audio_path_comb_inv = audio_path_comb.copy()
163    audio_path_comb_inv.loc[:, ['1', '0']] = audio_path_comb_inv.loc[:, ['0', '1']].values
164    audio_path_comb = concat([audio_path_comb, audio_path_comb_inv]).reset_index(drop=True)
165    audio_path_comb = audio_path_comb.sort_values(by=['0'])
166    logging.info("ABX combinations returned.")
167    return audio_path_comb

Reads files in a specified folder and generates combinations for ABX test.

Parameters
  • folder (str): Folder containing wav files.
  • parent (str, optional): Path to the project folder. Default is the current directory.
  • constant_reference (bool, optional): Determines whether to generate combinations for standard ABX (False) or CR-ABX (True). For CR-ABX, the combinations will have half the length of ABX. Default is False.
Returns
  • audio_path_comb (pandas.DataFrame): Sorted sets for ABX test.
Notes
  • The function reads the files in the specified folder and generates combinations of pairs.
  • Each combination is represented as a row in the returned DataFrame.
  • The DataFrame contains columns for the two audio paths in each combination, as well as an ID column.
  • If constant_reference is True, the reference audio path will be the same for all combinations. Otherwise, the reference audio path will vary for each combination.
  • The DataFrame is sorted by the first audio path in each combination.
Examples
>>> abx_combination("audio_folder", parent="project_folder", constant_reference=True)
Returns combinations for CR-ABX with a constant reference audio path.
>>> abx_combination("audio_folder")
Returns combinations for standard ABX.
def abx_combination_subset( folder: str, parent: str = '.', constant_reference: bool = False) -> pandas.core.frame.DataFrame:
169def abx_combination_subset(
170        folder: str,
171        parent: str=".",
172        constant_reference: bool=False
173        ) -> DataFrame:
174    '''Reads files in a specified folder and generates combinations for
175    ABX test. Creates a subset of combinations containing the first path
176    read.
177
178    Parameters
179    ----------
180    folder : str
181        Folder containing wav files.
182    parent : str, optional
183        Path to the project folder. Default is the current directory.
184    constant_reference : bool, optional
185        Determines whether to return combinations for standard ABX (False)
186        or CR-ABX (True) with half the length of ABX. Default is False.
187
188    Returns
189    -------
190    audio_path_comb : pandas.DataFrame
191        Sorted sets for ABX test.
192
193    Notes
194    -----
195    This function reads the files in the specified folder and generates
196    combinations for an ABX test. It creates a subset of combinations
197    that contain the first path read. The resulting combinations are
198    returned as a pandas DataFrame.
199
200    If `constant_reference` is True, the function generates combinations
201    for CR-ABX, where the reference path remains constant. If False, it
202    generates combinations for standard ABX, where the reference path
203    changes for each combination.
204
205    Examples
206    --------
207    >>> abx_combination_subset("audio_folder", parent="project_folder", constant_reference=True)
208    Returns combinations for CR-ABX with the first path as the reference.
209
210    >>> abx_combination_subset("audio_folder", constant_reference=False)
211    Returns combinations for standard ABX with the first path as the reference.
212    '''
213    audio_path_list = read_folder(folder, parent)
214    audio_path_comb = DataFrame(combinations(audio_path_list, 2), columns=['0', '1'])
215    audio_path_comb = audio_path_comb[audio_path_comb.loc[:,'0'] == audio_path_list[0]]
216    audio_path_comb['ID'] = audio_path_comb.index.format(name=False, formatter="{0:0=2d}".format)
217    if constant_reference:
218        audio_path_comb["Ref"] = audio_path_comb.loc[:, '0']
219    else:
220        audio_path_comb_copy = audio_path_comb.copy()
221        audio_path_comb["Ref"] = audio_path_comb.loc[:, '0']
222        audio_path_comb_copy["Ref"] = audio_path_comb_copy.loc[:, '1']
223        audio_path_comb = concat([audio_path_comb, audio_path_comb_copy])
224        
225    audio_path_comb_inv = audio_path_comb.copy()
226    audio_path_comb_inv.loc[:, ['0', '1']] = audio_path_comb_inv.loc[:, ['0', '1']].values
227    audio_path_comb = concat([audio_path_comb, audio_path_comb_inv]).reset_index(drop=True)
228    audio_path_comb = audio_path_comb.sort_values(by=['0'])
229    logging.info("ABX combinations returned.")
230    return audio_path_comb

Reads files in a specified folder and generates combinations for ABX test. Creates a subset of combinations containing the first path read.

Parameters
  • folder (str): Folder containing wav files.
  • parent (str, optional): Path to the project folder. Default is the current directory.
  • constant_reference (bool, optional): Determines whether to return combinations for standard ABX (False) or CR-ABX (True) with half the length of ABX. Default is False.
Returns
  • audio_path_comb (pandas.DataFrame): Sorted sets for ABX test.
Notes

This function reads the files in the specified folder and generates combinations for an ABX test. It creates a subset of combinations that contain the first path read. The resulting combinations are returned as a pandas DataFrame.

If constant_reference is True, the function generates combinations for CR-ABX, where the reference path remains constant. If False, it generates combinations for standard ABX, where the reference path changes for each combination.

Examples
>>> abx_combination_subset("audio_folder", parent="project_folder", constant_reference=True)
Returns combinations for CR-ABX with the first path as the reference.
>>> abx_combination_subset("audio_folder", constant_reference=False)
Returns combinations for standard ABX with the first path as the reference.
def adaptive_combination(folder: str, parent: str):
232def adaptive_combination(folder: str, parent: str):
233    '''Reads files in a specified folder and generates combinations for
234    adaptive method test.
235
236    Parameters
237    ----------
238    folder : str
239        Folder containing set subfolders.
240    parent : str
241        Path to project folder.
242
243    Returns
244    -------
245    audio_path_df : pandas.DataFrame
246        Sorted sets for adaptive method test.
247    '''
248    audio_path_df = DataFrame()
249    sets = sub_folders(folder, parent)
250    for s in sets:
251        paths = read_folder(s)
252        ids = [os.path.split(p)[1][:-4] for p in paths]
253        set_list = [os.path.split(s)[1] for p in paths]
254        dict_ = {'set': set_list, 'id': ids, 'path':paths}
255        df = DataFrame(dict_)
256        audio_path_df = concat([audio_path_df, df])
257    return audio_path_df

Reads files in a specified folder and generates combinations for adaptive method test.

Parameters
  • folder (str): Folder containing set subfolders.
  • parent (str): Path to project folder.
Returns
  • audio_path_df (pandas.DataFrame): Sorted sets for adaptive method test.
def adaptive_irs(folder: str):
259def adaptive_irs(folder: str):
260    '''Reads files in a specified folder and generates DataFrame
261
262    Parameters
263    ----------
264    folder : str
265        folder containing set subfolders
266
267    Returns
268    -------
269    audio_path_df : pandas.DataFrame
270        sorted irs for adaptive method test
271    '''
272    paths = read_folder(folder)
273    paths.sort()
274    ids = [os.path.split(p)[1][:-4] for p in paths]
275    dict_ = {'id': ids, 'path':paths}
276    audio_path_df = DataFrame(dict_)
277    
278    return audio_path_df

Reads files in a specified folder and generates DataFrame

Parameters
  • folder (str): folder containing set subfolders
Returns
  • audio_path_df (pandas.DataFrame): sorted irs for adaptive method test