listeningpy

GitHub repository

This library provides a way to design listening tests in Python.

The library contains several functions for audio processing, such as convolution or different types of normalization, including loudness normalization using the mosqito library.

Only ABX test protocol is currently supported, but more protocols will be added in the future.

Installation

It is currently not possible to install this library using pip or conda, please use the latest released package instead and install using pip locally.

Documentation

API documentation can be found here.

Example usage

The following script implements a basic ABX listening test using the listeningpy library.

More examples are to be added in the future to the examples folder.

import customtkinter as ctk
import logging
import argparse

from pandas import DataFrame
from time import strftime
from listeningpy.gui import abx
from listeningpy.gui.gui import InitFrame
from listeningpy.set_preparation import abx_combination, randomization
from listeningpy.processing import straight

logging.basicConfig(datefmt='%H:%M:%S',
                    level=logging.INFO)

class ABXTest(ctk.CTk):
    '''Main class for the ABX test GUI.'''
    def __init__(self, **kwargs):
        ctk.CTk.__init__(self, **kwargs)
        self._frame = None

    def switch_frame(self, new_frame):
        '''Destroys current frame and replaces it with a new one.'''
        if self._frame is not None:
            self._frame.destroy()
        self._frame = new_frame
        self._frame.place(relx=0.5, rely=0.5, anchor=ctk.CENTER)


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-sounds', default='stimuli', help='Directory path for sounds')
    args = parser.parse_args()

    sounds_dir = args.sounds

    # Read files in the specified folder and generate combinations for ABX test
    df = abx_combination(sounds_dir, '.', constant_reference=False)
    df = randomization(df)

    # Create root window and GUI
    root = ABXTest()
    root.title('ABX test v0.0.1')
    test = abx.Abx(root,
        df, 
        processing_func=straight,
        )
    init = InitFrame(root, test)
    root._frame = init
    init.place(relx=0.5, rely=0.5, anchor=ctk.CENTER)

    root.mainloop()

    init_dict = {
        'first_name': init.first_name,
        'second_name': init.second_name,
        'date_birth': init.date_of_birth,
        'gender': init.gender,
        'hearing_impaired': init.hear_impaired
    }
    timestamp = strftime("%y-%m-%d_%H-%M")

    # Save user's information and test results to CSV files
    DataFrame(init_dict, index=[0]).to_csv(
        f'{timestamp}_{init.first_name}_'+
        f'{init.second_name}_info.csv'
    )
    test.combinations.to_csv(
        f'{timestamp}_{init.first_name}_'+
        f'{init.second_name}_results.csv'
    )

Acknowledgments

This library was created thanks to the FAST-J-23-8284 project.

Special thanks to Prof. Monika Rychtarikova for her help with the theory and design of the listening tests and also to Prof. Christ Glorieux, Yannick Sluyts and Dominika Hudokova for their valuable feedback.

Github Copilot was used to generate parts of the documentation and code.

Author

Contributing

Pull requests are welcome. For any changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

GNU GPLv3

  1"""
  2[GitHub repository](https://github.com/vyhyb/listeningpy)
  3
  4This library provides a way to design listening tests in Python.
  5
  6The library contains several functions for audio processing, such as convolution or different types of normalization, including loudness normalization using the [mosqito](https://github.com/Eomys/MoSQITo) library.  
  7
  8Only ABX test protocol is currently supported, but more protocols will be added in the future.
  9
 10## Installation
 11
 12It is currently not possible to install this library using `pip` or `conda`, please use the latest [released package](https://github.com/vyhyb/listeningpy/releases) instead and install using [`pip` locally](https://packaging.python.org/en/latest/tutorials/installing-packages/).
 13
 14## Documentation
 15
 16API documentation can be found [here](https://vyhyb.github.io/listeningpy/).
 17
 18## Example usage
 19
 20The following script implements a basic ABX listening test using the listeningpy library.
 21
 22More examples are to be added in the future to the [examples](https://github.com/vyhyb/listeningpy/examples) folder.
 23
 24```python
 25import customtkinter as ctk
 26import logging
 27import argparse
 28
 29from pandas import DataFrame
 30from time import strftime
 31from listeningpy.gui import abx
 32from listeningpy.gui.gui import InitFrame
 33from listeningpy.set_preparation import abx_combination, randomization
 34from listeningpy.processing import straight
 35
 36logging.basicConfig(datefmt='%H:%M:%S',
 37                    level=logging.INFO)
 38
 39class ABXTest(ctk.CTk):
 40    '''Main class for the ABX test GUI.'''
 41    def __init__(self, **kwargs):
 42        ctk.CTk.__init__(self, **kwargs)
 43        self._frame = None
 44
 45    def switch_frame(self, new_frame):
 46        '''Destroys current frame and replaces it with a new one.'''
 47        if self._frame is not None:
 48            self._frame.destroy()
 49        self._frame = new_frame
 50        self._frame.place(relx=0.5, rely=0.5, anchor=ctk.CENTER)
 51
 52
 53if __name__ == '__main__':
 54    parser = argparse.ArgumentParser()
 55    parser.add_argument('-sounds', default='stimuli', help='Directory path for sounds')
 56    args = parser.parse_args()
 57
 58    sounds_dir = args.sounds
 59
 60    # Read files in the specified folder and generate combinations for ABX test
 61    df = abx_combination(sounds_dir, '.', constant_reference=False)
 62    df = randomization(df)
 63
 64    # Create root window and GUI
 65    root = ABXTest()
 66    root.title('ABX test v0.0.1')
 67    test = abx.Abx(root,
 68        df, 
 69        processing_func=straight,
 70        )
 71    init = InitFrame(root, test)
 72    root._frame = init
 73    init.place(relx=0.5, rely=0.5, anchor=ctk.CENTER)
 74
 75    root.mainloop()
 76    
 77    init_dict = {
 78        'first_name': init.first_name,
 79        'second_name': init.second_name,
 80        'date_birth': init.date_of_birth,
 81        'gender': init.gender,
 82        'hearing_impaired': init.hear_impaired
 83    }
 84    timestamp = strftime("%y-%m-%d_%H-%M")
 85    
 86    # Save user's information and test results to CSV files
 87    DataFrame(init_dict, index=[0]).to_csv(
 88        f'{timestamp}_{init.first_name}_'+
 89        f'{init.second_name}_info.csv'
 90    )
 91    test.combinations.to_csv(
 92        f'{timestamp}_{init.first_name}_'+
 93        f'{init.second_name}_results.csv'
 94    )
 95```
 96
 97## Acknowledgments
 98
 99This library was created thanks to the [FAST-J-23-8284](https://www.vut.cz/vav/projekty/detail/35091) project.
100
101Special thanks to Prof. Monika Rychtarikova for her help with the theory and design of the listening tests and also to Prof. Christ Glorieux, Yannick Sluyts and Dominika Hudokova for their valuable feedback.
102
103Github Copilot was used to generate parts of the documentation and code.
104
105## Author
106
107- [David Jun](https://www.fce.vutbr.cz/o-fakulte/lide/david-jun-12801/)
108  
109  PhD student at [Brno University of Technology](https://www.vutbr.cz/en/) and [KU Leuven](https://www.kuleuven.be/english/)
110
111## Contributing
112
113Pull requests are welcome. For any changes, please open an issue first
114to discuss what you would like to change.
115
116Please make sure to update tests as appropriate.
117
118## License
119
120[GNU GPLv3](https://choosealicense.com/licenses/gpl-3.0/)
121
122"""
123
124from .audiotools import audio_stats
125from .processing import (
126    straight,
127    gain_adjustment,
128    convolution,
129    match_fs,
130    audio_stats_logging,
131    )
132from .stimuli import play_sound