File size: 3,347 Bytes
127b976
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import argparse
import random
from pathlib import Path
import pandas as pd


def collect_audio_files(chunks_root):
    chunks_root = Path(chunks_root)
    audio_exts = {".wav", ".flac", ".mp3"}

    files = []
    for p in chunks_root.rglob("*"):
        if p.is_file() and p.suffix.lower() in audio_exts:
            files.append(p)

    return sorted(files)


def group_by_original_audio(files):
    """

    Groups chunks by their parent folder.

    This avoids putting chunks from the same long interview

    into both train and validation/test.

    """
    groups = {}

    for f in files:
        group_name = str(f.parent)
        groups.setdefault(group_name, []).append(f)

    return list(groups.values())


def split_groups(groups, train_ratio, val_ratio, seed):
    random.seed(seed)
    random.shuffle(groups)

    n = len(groups)
    n_train = int(n * train_ratio)
    n_val = int(n * val_ratio)

    train_groups = groups[:n_train]
    val_groups = groups[n_train:n_train + n_val]
    test_groups = groups[n_train + n_val:]

    return train_groups, val_groups, test_groups


def flatten(groups):
    out = []
    for g in groups:
        out.extend(g)
    return out


def make_df(files, dataset_name, split):
    rows = []

    for f in files:
        rows.append({
            "file_path": f.resolve().as_posix(),
            "binary_label": 0,
            "attack_type": "bonafide",
            "start_fake": -1,
            "end_fake": -1,
            "dataset": dataset_name,
            "split": split
        })

    return pd.DataFrame(rows)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--chunks-root", required=True)
    parser.add_argument("--dataset-name", required=True)
    parser.add_argument("--out-dir", required=True)
    parser.add_argument("--train-ratio", type=float, default=0.8)
    parser.add_argument("--val-ratio", type=float, default=0.1)
    parser.add_argument("--seed", type=int, default=42)
    args = parser.parse_args()

    files = collect_audio_files(args.chunks_root)

    if not files:
        raise RuntimeError(f"No audio files found in {args.chunks_root}")

    groups = group_by_original_audio(files)

    train_groups, val_groups, test_groups = split_groups(
        groups,
        args.train_ratio,
        args.val_ratio,
        args.seed
    )

    out_dir = Path(args.out_dir)
    out_dir.mkdir(parents=True, exist_ok=True)

    train_df = make_df(flatten(train_groups), args.dataset_name, "train")
    val_df = make_df(flatten(val_groups), args.dataset_name, "val")
    test_df = make_df(flatten(test_groups), args.dataset_name, "test")

    train_df.to_csv(out_dir / f"{args.dataset_name.lower()}_train.csv", index=False)
    val_df.to_csv(out_dir / f"{args.dataset_name.lower()}_val.csv", index=False)
    test_df.to_csv(out_dir / f"{args.dataset_name.lower()}_test.csv", index=False)

    print(f"Dataset: {args.dataset_name}")
    print(f"Total audio chunks: {len(files)}")
    print(f"Original audio groups: {len(groups)}")
    print(f"Train chunks: {len(train_df)}")
    print(f"Val chunks: {len(val_df)}")
    print(f"Test chunks: {len(test_df)}")
    print(f"Saved to: {out_dir}")


if __name__ == "__main__":
    main()