diff --git a/docs/index.md b/docs/index.md index 1b0c54ba1a21d65d45e9c72a29dc019a24432e97..d1baf50e03a9507b1f13ea6304091915ec19cc0e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,8 +16,14 @@ This is because VA interfaces make use of prototyping methods, which usually hav ::: vapython.va.VA -::: vapython._helper.possible_aura_modes +::: vapython._helper.possible_auralization_modes handler: python options: show_if_no_docstring: true - line_length: 60 \ No newline at end of file + line_length: 60 + +::: vapython._helper.default_auralization_mode + handler: python + options: + show_if_no_docstring: true + line_length: 60 diff --git a/src/vapython/_helper.py b/src/vapython/_helper.py index d509498017e51f6dac925e55010b6a382c70cf31..06f09ec2f86313fd853780ee57fdf8307c19bd18 100644 --- a/src/vapython/_helper.py +++ b/src/vapython/_helper.py @@ -13,7 +13,7 @@ from typing import Optional from platformdirs import user_config_dir -possible_aura_modes = { +possible_auralization_modes = { "Nothing": (0, "Nothing"), "DS": (1 << 0, "Direct Sound"), "ER": (1 << 1, "Early Reflections"), @@ -29,21 +29,33 @@ possible_aura_modes = { "TR": (1 << 11, "Transmission Loss"), "AB": (1 << 12, "Absorption"), } +""" +Dictionary containing all possible auralization modes. -default_aura_mode = sum( +Auralization modes allow to enable or disable specific effects in the auralization process during runtime. +A more in-depth explanation of each auralization mode can be found [here](https://www.virtualacoustics.de/VA/documentation/control/#global-auralization-mode). +""" + +default_auralization_mode = sum( [ - possible_aura_modes["DS"][0], - possible_aura_modes["SD"][0], - possible_aura_modes["MA"][0], - possible_aura_modes["DP"][0], - possible_aura_modes["SL"][0], - possible_aura_modes["TR"][0], - possible_aura_modes["AB"][0], + possible_auralization_modes["DS"][0], + possible_auralization_modes["SD"][0], + possible_auralization_modes["MA"][0], + possible_auralization_modes["DP"][0], + possible_auralization_modes["SL"][0], + possible_auralization_modes["TR"][0], + possible_auralization_modes["AB"][0], ] ) +""" +Set of default auralization modes. + +For more information see [`possible_auralization_modes`][vapython._helper.possible_auralization_modes] and the +[VA documentation](https://www.virtualacoustics.de/VA/documentation/control/#global-auralization-mode). +""" -def parse_aura_mode_str(input_string: str, aura_mode: int = default_aura_mode) -> int: +def parse_aura_mode_str(input_string: str, aura_mode: int = default_auralization_mode) -> int: """Parses the input string and returns the corresponding auralization mode as an integer. The input string can contain a list of auralization modes separated by commas. Each auralization mode can be @@ -76,10 +88,10 @@ def parse_aura_mode_str(input_string: str, aura_mode: int = default_aura_mode) - return 0 # No aura mode if input_string == "*": - return sum(m[0] for m in possible_aura_modes.values()) # All aura modes + return sum(m[0] for m in possible_auralization_modes.values()) # All aura modes if input_string.lower() == "default": - return default_aura_mode + return default_auralization_mode split_input = re.findall(r"(?:(\+|-)([A-Z]{2})(?:,|$))+?", input_string, re.IGNORECASE) @@ -88,14 +100,14 @@ def parse_aura_mode_str(input_string: str, aura_mode: int = default_aura_mode) - for sign, mode in split_input: # check if mode is valid - if mode not in possible_aura_modes: + if mode not in possible_auralization_modes: msg = f"Invalid aura mode: {mode}" raise ValueError(msg) if sign == "+": - enable.append(possible_aura_modes[mode][0]) + enable.append(possible_auralization_modes[mode][0]) else: - disable.append(possible_aura_modes[mode][0]) + disable.append(possible_auralization_modes[mode][0]) aura_mode = aura_mode | sum(enable) aura_mode = aura_mode & ~sum(disable) @@ -112,7 +124,7 @@ def convert_aura_mode_to_str(aura_mode: int, *, short_form: bool = True) -> str: - All modes: "All" - Default modes, see [`default_aura_mode`][vapython._helpers.default_aura_mode]: "Default" - See also [`possible_aura_modes`][vapython._helpers.possible_aura_modes] for all possible aura modes. + See also [`possible_auralization_modes`][vapython._helpers.possible_auralization_modes] for all possible aura modes. Examples: >>> convert_aura_mode_to_str(0) @@ -137,15 +149,15 @@ def convert_aura_mode_to_str(aura_mode: int, *, short_form: bool = True) -> str: if aura_mode == 0 and not short_form: return "Nothing" - if aura_mode == sum(m[0] for m in possible_aura_modes.values()) and not short_form: + if aura_mode == sum(m[0] for m in possible_auralization_modes.values()) and not short_form: return "All" - if aura_mode == default_aura_mode and not short_form: + if aura_mode == default_auralization_mode and not short_form: return "Default" aura_modes = [] - for mode, (value, name) in possible_aura_modes.items(): + for mode, (value, name) in possible_auralization_modes.items(): if aura_mode & value: if short_form: aura_modes.append(mode) diff --git a/src/vapython/examples/__main__.py b/src/vapython/examples/__main__.py index 1e3f4b5d162f3d70ca8406bab315b9430b58c72b..a1937fede176c43094e5450c8a8e4007f29b0bf3 100644 --- a/src/vapython/examples/__main__.py +++ b/src/vapython/examples/__main__.py @@ -4,6 +4,17 @@ from pathlib import Path def main(): + """ + Main function to list and execute example scripts. + This function performs the following steps: + 1. Lists all Python files in the current directory that contain "example" in their name. + 2. If no command-line arguments are provided, it prints the list of example files and prompts the user to select one by index. + 3. If a command-line argument is provided, it uses that as the index of the example file to run. + 4. Validates the selected index and either exits, prints an error message, or imports and runs the selected example's main function. + Returns: + None + """ + current_path = Path(__file__).parent example_files = list(current_path.glob("*example*.py")) diff --git a/src/vapython/va.py b/src/vapython/va.py index 0d7258105e69a231821961c37f85b27c79ffbae1..df73fa44cff067cdcd9330b65109efebf78c9b35 100644 --- a/src/vapython/va.py +++ b/src/vapython/va.py @@ -138,7 +138,7 @@ class VA(VAInterface): ) def set_global_auralization_mode(self, mode: str) -> None: # type: ignore[override] - """Set the global auralization mode. + """Set the [global auralization mode](https://www.virtualacoustics.org/VA/documentation/control/#global-auralization-mode). Args: mode: The auralization mode to set. @@ -590,12 +590,22 @@ class VA(VAInterface): This function connects to a tracking system to track sound sources or receivers. The tracking system can be used to track the position and orientation of sound sources and receivers. + Sources and receivers can be set as "tracked" via the respective `set_tracked_*` functions. + These methods can be used before or after connecting to the tracking system. + Via the `tracker` argument, the tracking system can be selected. Without the IHTATrackingPython package, only the NatNet tracking system is available. Args: server_ip: The IP address of the tracking server. tracker: The tracking system to use. Defaults to `NatNet`. + + Examples: + This will connect to a NatNet tracking system running on the same computer and track a + sound source with the second rigid body. + + >>> va.connect_tracker("127.0.0.1") + >>> va.set_tracked_sound_source(sound_source, 1) """ from vapython.tracking import Tracker @@ -672,6 +682,8 @@ class VA(VAInterface): This function sets a sound source to be tracked by the tracking system. The sound source will be tracked with the given `tracker_id`. + This method can be called before or after connecting to the tracking system. + Args: sound_source_id: The ID of the sound source to track. tracker_id: The ID of the tracker to use. @@ -684,6 +696,8 @@ class VA(VAInterface): This function sets a sound receiver to be tracked by the tracking system. The sound receiver will be tracked with the given `tracker_id`. + This method can be called before or after connecting to the tracking system. + Args: sound_receiver_id: The ID of the sound receiver to track. tracker_id: The ID of the tracker to use. @@ -698,6 +712,8 @@ class VA(VAInterface): The rotation of the torso will influence the HRIR selection. + This method can be called before or after connecting to the tracking system. + Args: sound_receiver_id: The ID of the sound receiver torso to track. tracker_id: The ID of the tracker to use. @@ -710,6 +726,8 @@ class VA(VAInterface): This function sets a real-world sound receiver to be tracked by the tracking system. The real-world sound receiver will be tracked with the given `tracker_id`. + This method can be called before or after connecting to the tracking system. + Args: sound_receiver_id: The ID of the real-world sound receiver to track. tracker_id: The ID of the tracker to use. @@ -724,6 +742,8 @@ class VA(VAInterface): The rotation of the torso will influence the HRIR selection. + This method can be called before or after connecting to the tracking system. + Args: sound_receiver_id: The ID of the real-world sound receiver torso to track. tracker_id: The ID of the tracker to use. @@ -768,6 +788,9 @@ class VA(VAInterface): ) -> None: """Set the offset for a tracked sound receiver. + This can be useful if the origin of the rigid body does not align with the acoustic center. + For example, a tracker mounted on top of a head should still have the acoustic center at ear height. + The orientation offset is applied directly to the orientation of the sound receiver. The position offset is first rotated by the orientation of the sound receiver and then applied. @@ -794,6 +817,8 @@ class VA(VAInterface): ) -> None: """Set the offset for a tracked sound receiver torso. + This can be useful if the origin of the rigid body does not align with the acoustic center. + Args: sound_receiver_id: The ID of the sound receiver torso to set the offset for. @@ -816,6 +841,9 @@ class VA(VAInterface): ) -> None: """Set the offset for a tracked real-world sound receiver. + This can be useful if the origin of the rigid body does not align with the acoustic center. + For example, a tracker mounted on top of a head should still have the acoustic center at ear height. + The orientation offset is applied directly to the orientation of the sound receiver. The position offset is first rotated by the orientation of the sound receiver and then applied. @@ -842,6 +870,8 @@ class VA(VAInterface): ) -> None: """Set the offset for a tracked real-world sound receiver torso. + This can be useful if the origin of the rigid body does not align with the acoustic center. + Args: sound_receiver_id: The ID of the real-world sound receiver torso to set the offset for. orientation_offset: The orientation offset to set. diff --git a/tests/helper_test.py b/tests/helper_test.py index dda4e6d90c1660e17da5ac21d581551b3e397b1a..0a02728d3db2a20792dba96113925c0563154555 100644 --- a/tests/helper_test.py +++ b/tests/helper_test.py @@ -8,10 +8,10 @@ import pytest from vapython._helper import ( convert_aura_mode_to_str, - default_aura_mode, + default_auralization_mode, find_server_executable, parse_aura_mode_str, - possible_aura_modes, + possible_auralization_modes, ) @@ -20,10 +20,10 @@ def test_parse_aura_mode_str(): assert parse_aura_mode_str("", 0) == 0 # Test case 2: Input string "*" should return the sum of all possible aura modes - assert parse_aura_mode_str("*", 0) == sum(m[0] for m in possible_aura_modes.values()) + assert parse_aura_mode_str("*", 0) == sum(m[0] for m in possible_auralization_modes.values()) # Test case 3: Input string "default" should return the default aura mode - assert parse_aura_mode_str("default", 0) == default_aura_mode + assert parse_aura_mode_str("default", 0) == default_auralization_mode # Test case 4: Input string "+AB,-SD" should enable AB and disable SD assert parse_aura_mode_str("+AB,-SD", 0) == 4096 @@ -36,8 +36,8 @@ def test_parse_aura_mode_str(): # Test case 7: Input string "-DS,+ER,SD" with aura_mode = default_aura_mode should disable DS, enable ER assert ( - parse_aura_mode_str("-DS,+ER,SD", default_aura_mode) - == default_aura_mode - possible_aura_modes["DS"][0] + possible_aura_modes["ER"][0] + parse_aura_mode_str("-DS,+ER,SD", default_auralization_mode) + == default_auralization_mode - possible_auralization_modes["DS"][0] + possible_auralization_modes["ER"][0] ) @@ -57,11 +57,11 @@ def test_convert_aura_mode_to_str(): assert convert_aura_mode_to_str(0, short_form=True) == "" # Test case 2: aura_mode = sum of all possible_aura_modes values, aura_mode = 8191 (binary: 1111111111111) - assert convert_aura_mode_to_str(sum(m[0] for m in possible_aura_modes.values()), short_form=False) == "All" + assert convert_aura_mode_to_str(sum(m[0] for m in possible_auralization_modes.values()), short_form=False) == "All" assert convert_aura_mode_to_str(8191) == "DS,ER,DD,SD,MA,TV,SC,DF,NF,DP,SL,TR,AB" # Test case 3: aura_mode = default_aura_mode - assert convert_aura_mode_to_str(default_aura_mode, short_form=False) == "Default" + assert convert_aura_mode_to_str(default_auralization_mode, short_form=False) == "Default" # Test case 4: aura_mode = 5 (binary: 101) assert convert_aura_mode_to_str(5) == "DS,DD"