We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
A few questions...
I came across a few confusions while I was reading the code in order to write an example. It would be helpful for me if they are clarified ( I may have missed something).

https://github.com/lhotse-speech/lhotse/blob/master/lhotse/kaldi.py#L68
why `duration - start` rather than just `duration`?

https://github.com/lhotse-speech/lhotse/blob/master/lhotse/audio.py#L178
why not `[n_sources, n_channels, n_samples]`?

Thanks!

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lhotse/kaldi.py`
Content:
```
1 from collections import defaultdict
2 from pathlib import Path
3 from typing import Dict, Optional, Tuple
4 
5 from lhotse.audio import AudioSource, Recording, RecordingSet
6 from lhotse.supervision import SupervisionSegment, SupervisionSet
7 from lhotse.utils import Pathlike
8 
9 
10 def load_kaldi_data_dir(path: Pathlike, sampling_rate: int) -> Tuple[RecordingSet, Optional[SupervisionSet]]:
11     """
12     Load a Kaldi data directory and convert it to a Lhotse RecordingSet and SupervisionSet manifests.
13     For this to work, at least the wav.scp file must exist.
14     SupervisionSet is created only when a segments file exists.
15     All the other files (text, utt2spk, etc.) are optional, and some of them might not be handled yet.
16     In particular, feats.scp files are ignored.
17     """
18     path = Path(path)
19     assert path.is_dir()
20 
21     # must exist for RecordingSet
22     recordings = load_kaldi_text_mapping(path / 'wav.scp', must_exist=True)
23 
24     durations = defaultdict(float)
25     reco2dur = path / 'reco2dur'
26     if not reco2dur.is_file():
27         raise ValueError(f"No such file: '{reco2dur}' -- fix it by running: utils/data/get_reco2dur.sh <data-dir>")
28     with reco2dur.open() as f:
29         for line in f:
30             recording_id, dur = line.strip().split()
31             durations[recording_id] = float(dur)
32 
33     audio_set = RecordingSet.from_recordings(
34         Recording(
35             id=recording_id,
36             sources=[
37                 AudioSource(
38                     type='command' if path_or_cmd.endswith('|') else 'file',
39                     channels=[0],
40                     source=path_or_cmd[:-1] if path_or_cmd.endswith('|') else path_or_cmd
41                 )
42             ],
43             sampling_rate=sampling_rate,
44             num_samples=int(durations[recording_id] * sampling_rate),
45             duration=durations[recording_id]
46         )
47         for recording_id, path_or_cmd in recordings.items()
48     )
49 
50     # must exist for SupervisionSet
51     segments = path / 'segments'
52     if not segments.is_file():
53         return audio_set, None
54 
55     with segments.open() as f:
56         supervision_segments = [l.strip().split() for l in f]
57 
58     texts = load_kaldi_text_mapping(path / 'text')
59     speakers = load_kaldi_text_mapping(path / 'utt2spk')
60     genders = load_kaldi_text_mapping(path / 'spk2gender')
61     languages = load_kaldi_text_mapping(path / 'utt2lang')
62 
63     supervision_set = SupervisionSet.from_segments(
64         SupervisionSegment(
65             id=segment_id,
66             recording_id=recording_id,
67             start=float(start),
68             duration=float(duration) - float(start),
69             channel=0,
70             text=texts[segment_id],
71             language=languages[segment_id],
72             speaker=speakers[segment_id],
73             gender=genders[speakers[segment_id]]
74         )
75         for segment_id, recording_id, start, duration in supervision_segments
76     )
77 
78     return audio_set, supervision_set
79 
80 
81 def load_kaldi_text_mapping(path: Path, must_exist: bool = False) -> Dict[str, Optional[str]]:
82     """Load Kaldi files such as utt2spk, spk2gender, text, etc. as a dict."""
83     mapping = defaultdict(lambda: None)
84     if path.is_file():
85         with path.open() as f:
86             mapping = dict(line.strip().split(' ', maxsplit=1) for line in f)
87     elif must_exist:
88         raise ValueError(f"No such file: {path}")
89     return mapping
90
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lhotse/kaldi.py b/lhotse/kaldi.py
--- a/lhotse/kaldi.py
+++ b/lhotse/kaldi.py
@@ -65,14 +65,14 @@
             id=segment_id,
             recording_id=recording_id,
             start=float(start),
-            duration=float(duration) - float(start),
+            duration=float(end) - float(start),
             channel=0,
             text=texts[segment_id],
             language=languages[segment_id],
             speaker=speakers[segment_id],
             gender=genders[speakers[segment_id]]
         )
-        for segment_id, recording_id, start, duration in supervision_segments
+        for segment_id, recording_id, start, end in supervision_segments
     )
 
     return audio_set, supervision_set

{"golden_diff": "diff --git a/lhotse/kaldi.py b/lhotse/kaldi.py\n--- a/lhotse/kaldi.py\n+++ b/lhotse/kaldi.py\n@@ -65,14 +65,14 @@\n             id=segment_id,\n             recording_id=recording_id,\n             start=float(start),\n-            duration=float(duration) - float(start),\n+            duration=float(end) - float(start),\n             channel=0,\n             text=texts[segment_id],\n             language=languages[segment_id],\n             speaker=speakers[segment_id],\n             gender=genders[speakers[segment_id]]\n         )\n-        for segment_id, recording_id, start, duration in supervision_segments\n+        for segment_id, recording_id, start, end in supervision_segments\n     )\n \n     return audio_set, supervision_set\n", "issue": "A few questions...\nI came across a few confusions while I was reading the code in order to write an example. It would be helpful for me if they are clarified ( I may have missed something).\r\n\r\nhttps://github.com/lhotse-speech/lhotse/blob/master/lhotse/kaldi.py#L68\r\nwhy `duration - start` rather than just `duration`?\r\n\r\nhttps://github.com/lhotse-speech/lhotse/blob/master/lhotse/audio.py#L178\r\nwhy not `[n_sources, n_channels, n_samples]`?\r\n\r\nThanks!\n", "before_files": [{"content": "from collections import defaultdict\nfrom pathlib import Path\nfrom typing import Dict, Optional, Tuple\n\nfrom lhotse.audio import AudioSource, Recording, RecordingSet\nfrom lhotse.supervision import SupervisionSegment, SupervisionSet\nfrom lhotse.utils import Pathlike\n\n\ndef load_kaldi_data_dir(path: Pathlike, sampling_rate: int) -> Tuple[RecordingSet, Optional[SupervisionSet]]:\n    \"\"\"\n    Load a Kaldi data directory and convert it to a Lhotse RecordingSet and SupervisionSet manifests.\n    For this to work, at least the wav.scp file must exist.\n    SupervisionSet is created only when a segments file exists.\n    All the other files (text, utt2spk, etc.) are optional, and some of them might not be handled yet.\n    In particular, feats.scp files are ignored.\n    \"\"\"\n    path = Path(path)\n    assert path.is_dir()\n\n    # must exist for RecordingSet\n    recordings = load_kaldi_text_mapping(path / 'wav.scp', must_exist=True)\n\n    durations = defaultdict(float)\n    reco2dur = path / 'reco2dur'\n    if not reco2dur.is_file():\n        raise ValueError(f\"No such file: '{reco2dur}' -- fix it by running: utils/data/get_reco2dur.sh <data-dir>\")\n    with reco2dur.open() as f:\n        for line in f:\n            recording_id, dur = line.strip().split()\n            durations[recording_id] = float(dur)\n\n    audio_set = RecordingSet.from_recordings(\n        Recording(\n            id=recording_id,\n            sources=[\n                AudioSource(\n                    type='command' if path_or_cmd.endswith('|') else 'file',\n                    channels=[0],\n                    source=path_or_cmd[:-1] if path_or_cmd.endswith('|') else path_or_cmd\n                )\n            ],\n            sampling_rate=sampling_rate,\n            num_samples=int(durations[recording_id] * sampling_rate),\n            duration=durations[recording_id]\n        )\n        for recording_id, path_or_cmd in recordings.items()\n    )\n\n    # must exist for SupervisionSet\n    segments = path / 'segments'\n    if not segments.is_file():\n        return audio_set, None\n\n    with segments.open() as f:\n        supervision_segments = [l.strip().split() for l in f]\n\n    texts = load_kaldi_text_mapping(path / 'text')\n    speakers = load_kaldi_text_mapping(path / 'utt2spk')\n    genders = load_kaldi_text_mapping(path / 'spk2gender')\n    languages = load_kaldi_text_mapping(path / 'utt2lang')\n\n    supervision_set = SupervisionSet.from_segments(\n        SupervisionSegment(\n            id=segment_id,\n            recording_id=recording_id,\n            start=float(start),\n            duration=float(duration) - float(start),\n            channel=0,\n            text=texts[segment_id],\n            language=languages[segment_id],\n            speaker=speakers[segment_id],\n            gender=genders[speakers[segment_id]]\n        )\n        for segment_id, recording_id, start, duration in supervision_segments\n    )\n\n    return audio_set, supervision_set\n\n\ndef load_kaldi_text_mapping(path: Path, must_exist: bool = False) -> Dict[str, Optional[str]]:\n    \"\"\"Load Kaldi files such as utt2spk, spk2gender, text, etc. as a dict.\"\"\"\n    mapping = defaultdict(lambda: None)\n    if path.is_file():\n        with path.open() as f:\n            mapping = dict(line.strip().split(' ', maxsplit=1) for line in f)\n    elif must_exist:\n        raise ValueError(f\"No such file: {path}\")\n    return mapping\n", "path": "lhotse/kaldi.py"}], "after_files": [{"content": "from collections import defaultdict\nfrom pathlib import Path\nfrom typing import Dict, Optional, Tuple\n\nfrom lhotse.audio import AudioSource, Recording, RecordingSet\nfrom lhotse.supervision import SupervisionSegment, SupervisionSet\nfrom lhotse.utils import Pathlike\n\n\ndef load_kaldi_data_dir(path: Pathlike, sampling_rate: int) -> Tuple[RecordingSet, Optional[SupervisionSet]]:\n    \"\"\"\n    Load a Kaldi data directory and convert it to a Lhotse RecordingSet and SupervisionSet manifests.\n    For this to work, at least the wav.scp file must exist.\n    SupervisionSet is created only when a segments file exists.\n    All the other files (text, utt2spk, etc.) are optional, and some of them might not be handled yet.\n    In particular, feats.scp files are ignored.\n    \"\"\"\n    path = Path(path)\n    assert path.is_dir()\n\n    # must exist for RecordingSet\n    recordings = load_kaldi_text_mapping(path / 'wav.scp', must_exist=True)\n\n    durations = defaultdict(float)\n    reco2dur = path / 'reco2dur'\n    if not reco2dur.is_file():\n        raise ValueError(f\"No such file: '{reco2dur}' -- fix it by running: utils/data/get_reco2dur.sh <data-dir>\")\n    with reco2dur.open() as f:\n        for line in f:\n            recording_id, dur = line.strip().split()\n            durations[recording_id] = float(dur)\n\n    audio_set = RecordingSet.from_recordings(\n        Recording(\n            id=recording_id,\n            sources=[\n                AudioSource(\n                    type='command' if path_or_cmd.endswith('|') else 'file',\n                    channels=[0],\n                    source=path_or_cmd[:-1] if path_or_cmd.endswith('|') else path_or_cmd\n                )\n            ],\n            sampling_rate=sampling_rate,\n            num_samples=int(durations[recording_id] * sampling_rate),\n            duration=durations[recording_id]\n        )\n        for recording_id, path_or_cmd in recordings.items()\n    )\n\n    # must exist for SupervisionSet\n    segments = path / 'segments'\n    if not segments.is_file():\n        return audio_set, None\n\n    with segments.open() as f:\n        supervision_segments = [l.strip().split() for l in f]\n\n    texts = load_kaldi_text_mapping(path / 'text')\n    speakers = load_kaldi_text_mapping(path / 'utt2spk')\n    genders = load_kaldi_text_mapping(path / 'spk2gender')\n    languages = load_kaldi_text_mapping(path / 'utt2lang')\n\n    supervision_set = SupervisionSet.from_segments(\n        SupervisionSegment(\n            id=segment_id,\n            recording_id=recording_id,\n            start=float(start),\n            duration=float(end) - float(start),\n            channel=0,\n            text=texts[segment_id],\n            language=languages[segment_id],\n            speaker=speakers[segment_id],\n            gender=genders[speakers[segment_id]]\n        )\n        for segment_id, recording_id, start, end in supervision_segments\n    )\n\n    return audio_set, supervision_set\n\n\ndef load_kaldi_text_mapping(path: Path, must_exist: bool = False) -> Dict[str, Optional[str]]:\n    \"\"\"Load Kaldi files such as utt2spk, spk2gender, text, etc. as a dict.\"\"\"\n    mapping = defaultdict(lambda: None)\n    if path.is_file():\n        with path.open() as f:\n            mapping = dict(line.strip().split(' ', maxsplit=1) for line in f)\n    elif must_exist:\n        raise ValueError(f\"No such file: {path}\")\n    return mapping\n", "path": "lhotse/kaldi.py"}]}