Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix unstable audio channel order #358

Merged
merged 1 commit into from
Jan 10, 2025
Merged

Conversation

justjanne
Copy link
Contributor

@justjanne justjanne commented Jan 10, 2025

We used to order audio channels using enumerate(set(t.split("+"))). In Python, the iteration order for sets is random and changes with every run.

This commit uses a stable order (as specified in the config) instead

We used to order channels using enumerate(set(t.split("+"))). In Python, the iteration order for sets is random and changes with every run.

This commit uses a stable order (as specified in the config) instead
@justjanne
Copy link
Contributor Author

Demonstration of the issue:

test.py

streams = [None] * 10
for i, channel in enumerate(set("0+1+2+3+4+5+6+7+8+9".split("+"))):
    streams[i] = channel
print(streams)

Results in:

$ python3 test.py
['3', '0', '2', '5', '6', '1', '7', '9', '8', '4']

Every run has a different result:

$ for i in {0..10}; do python3 test.py; done
['3', '5', '9', '0', '1', '2', '6', '8', '4', '7']
['5', '4', '8', '6', '0', '1', '2', '9', '3', '7']
['8', '5', '3', '6', '0', '7', '9', '2', '1', '4']
['3', '7', '2', '1', '8', '5', '9', '6', '0', '4']
['6', '8', '0', '2', '3', '9', '7', '4', '5', '1']
['1', '8', '4', '7', '0', '3', '6', '2', '5', '9']
['9', '3', '4', '0', '7', '6', '8', '5', '1', '2']
['5', '1', '7', '4', '3', '0', '6', '9', '8', '2']
['1', '4', '5', '7', '9', '6', '0', '8', '3', '2']
['9', '5', '1', '2', '8', '7', '0', '6', '4', '3']
['7', '4', '0', '1', '5', '2', '6', '8', '3', '9']

@justjanne justjanne changed the title Fix issue where channel order was unstable Fix unstable audio channel order Jan 10, 2025
@justjanne
Copy link
Contributor Author

The code that runs is this:

for i, channel in enumerate(set(t.split("+"))):
    name = source if use_source_as_name else r.group(1)
    if self.has_stream(name):
        log.error("input audio stream name '%s' can't be addressed a second time within source '%s'", name, source)
    else:
        audiostreams.append(AudioStream(source, i, name, channel))

Assume we've got this configuration:

audio.cam1 = "0+1"

Then it gets parsed by t.split("+") into ["0", "1"]

Now set() deduplicates duplicate entries, but the order of sets is different every time python is launched, so there's a 50/50 chance for either ["0", "1"] or ["1", "0"]

Afterwards enumerate turns that into either [(0, "0"), (1, "1")] or [(0, "1"), (1, "0")].

Which means we either execute

audiostreams.append(AudioStream(source="cam1", channel=0, name="cam1", source_channel="0"))
audiostreams.append(AudioStream(source="cam1", channel=1, name="cam1", source_channel="1"))

or

audiostreams.append(AudioStream(source="cam1", channel=1, name="cam1", source_channel="0"))
audiostreams.append(AudioStream(source="cam1", channel=0, name="cam1", source_channel="1"))

Which then gets used in the audio mix matrix, which now has a 50/50 chance to be either

1 0
0 1

or

0 1
1 0

@Kunsi Kunsi merged commit 37ae38b into voc:main Jan 10, 2025
@Kunsi
Copy link
Contributor

Kunsi commented Jan 10, 2025

Thanks!

@justjanne justjanne deleted the fix-channel-order branch January 13, 2025 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants