File size: 3,145 Bytes
5a44508
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
120
121
"""Minimal usage example for hv-sign.

If you have FSDD, ESC-50, or another corpus locally, edit the paths.
Otherwise this file synthesizes a small corpus and runs the full suite.
"""
import math
import os
import wave
from array import array

from hv_sign import HVSign


OUTDIR = "./hv_sign_example"


def _write_wav(path: str, samples, sr: int = 16000) -> None:
    ints = array(
        "h",
        (max(-32768, min(32767, int(x * 32767))) for x in samples),
    )
    with wave.open(path, "wb") as w:
        w.setnchannels(1)
        w.setsampwidth(2)
        w.setframerate(sr)
        w.writeframes(ints.tobytes())


def _beeps(freqs, dur_ms, gap_ms, sr=16000):
    out = []
    for f in freqs:
        n = int(sr * dur_ms / 1000)
        for i in range(n):
            t = i / sr
            env = math.sin(math.pi * i / n) ** 0.5
            out.append(0.5 * env * math.sin(2 * math.pi * f * t))
        out.extend([0.0] * int(sr * gap_ms / 1000))
    return out


def _chirp(f0, f1, dur_ms, sr=16000):
    n = int(sr * dur_ms / 1000)
    dur_s = dur_ms / 1000.0
    out = []
    for i in range(n):
        t = i / sr
        phase = 2 * math.pi * (f0 * t + 0.5 * (f1 - f0) * t * t / dur_s)
        env = math.sin(math.pi * i / n)
        out.append(0.5 * env * math.sin(phase))
    return out


def main() -> None:
    os.makedirs(OUTDIR, exist_ok=True)

    # Synthesize a small corpus
    corpus = {
        "beeps_low": _beeps([220, 220, 220], 150, 100),
        "beeps_high": _beeps([880, 660, 440], 120, 90),
        "chirp_up": _chirp(200, 2000, 800),
        "mix_a": _beeps([220, 330, 440, 220, 550], 100, 80),
        "mix_b": _beeps([150, 900, 300, 1500, 200], 120, 70),
    }
    for name, sig in corpus.items():
        _write_wav(os.path.join(OUTDIR, f"{name}.wav"), sig)

    model = HVSign()

    # Single file
    first = os.path.join(OUTDIR, "beeps_low.wav")
    report = model.score_file(first)

    print("=" * 60)
    print("Single-file report")
    print("=" * 60)
    print(model.render_file(report))
    print()

    print("=" * 60)
    print("Numeric summary")
    print("=" * 60)
    print(f"  events       : {len(report.events)}")
    print(f"  unique fix   : {len(set(report.fixed_score))}")
    print(f"  fixed score  : {report.fixed_score}")
    print()

    # Corpus
    print("=" * 60)
    print("Corpus report")
    print("=" * 60)
    corpus_report = model.score_directory(OUTDIR)
    print(model.render_corpus(corpus_report))
    print()

    if corpus_report.discovered:
        d = corpus_report.discovered
        print("=" * 60)
        print("Discovered alphabet summary")
        print("=" * 60)
        print(f"  k            : {d.k}")
        print(f"  silhouette   : {d.silhouette:.4f}")
        print()

    # Decay
    print("=" * 60)
    print("Symbolic decay")
    print("=" * 60)
    decay = model.decay_analysis(first)
    print(model.render_decay(decay))
    print()

    print("=" * 60)
    print("Numeric summary")
    print("=" * 60)
    print(f"  symbolic SNR : {decay.symbolic_snr}")
    print(f"  note         : {decay.note}")
    print()


if __name__ == "__main__":
    main()