From cf4edbbf62426f01191a1c95b3a8d06d9eeb5d8d Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 19 Oct 2026 14:25:11 +0200 Subject: [PATCH] Add a distinct three-tone radio call ringtone for desktop and Android --- .../app/src/main/res/raw/radio_incoming.mp3 | Bin 0 -> 29420 bytes .../resources/sounds/radio_incoming.mp3 | Bin 0 -> 29420 bytes tools/generate_radio_ringtone.py | 52 ++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 tools/chatgui-android/app/src/main/res/raw/radio_incoming.mp3 create mode 100644 tools/chatgui/resources/sounds/radio_incoming.mp3 create mode 100644 tools/generate_radio_ringtone.py diff --git a/tools/chatgui-android/app/src/main/res/raw/radio_incoming.mp3 b/tools/chatgui-android/app/src/main/res/raw/radio_incoming.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..d896bce947325559d364b7a314825cdb5b469f29 GIT binary patch literal 29420 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 literal 0 HcmV?d00001 diff --git a/tools/chatgui/resources/sounds/radio_incoming.mp3 b/tools/chatgui/resources/sounds/radio_incoming.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..d896bce947325559d364b7a314825cdb5b469f29 GIT binary patch literal 29420 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 literal 0 HcmV?d00001 diff --git a/tools/generate_radio_ringtone.py b/tools/generate_radio_ringtone.py new file mode 100644 index 00000000..7cf61977 --- /dev/null +++ b/tools/generate_radio_ringtone.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +"""Создаёт общий рингтон рации для desktop и Android; нужен ffmpeg, без сторонних Python-модулей.""" + +import array +import math +from pathlib import Path +import shutil +import subprocess +import sys +import tempfile +import wave + + +def main(): + root = Path(__file__).resolve().parents[1] + rate = 48000 + duration = 2.4 + samples = array.array("h", [0]) * round(rate * duration) + # Три восходящих позывных с мягкими фронтами, затем пауза до следующего цикла. + for start, frequency in ((0.1, 660), (0.34, 880), (0.58, 1100)): + length = 0.16 + for i in range(round(rate * length)): + t = i / rate + envelope = min(1.0, t / 0.008, (length - t) / 0.035) + phase = 2 * math.pi * frequency * t + signal = (math.sin(phase) + 0.15 * math.sin(2 * phase)) / 1.15 + samples[round(start * rate) + i] = round(32767 * 0.42 * envelope * signal) + peak = max(abs(sample) for sample in samples) / 32767 + if sys.byteorder != "little": + samples.byteswap() + destinations = ( + root / "tools/chatgui/resources/sounds/radio_incoming.mp3", + root / "tools/chatgui-android/app/src/main/res/raw/radio_incoming.mp3", + ) + with tempfile.TemporaryDirectory(prefix="utun-radio-ring-") as directory: + source = Path(directory) / "radio.wav" + encoded = Path(directory) / "radio.mp3" + with wave.open(str(source), "wb") as output: + output.setparams((1, 2, rate, 0, "NONE", "not compressed")) + output.writeframes(samples.tobytes()) + subprocess.run( + ["ffmpeg", "-v", "error", "-y", "-i", str(source), "-codec:a", "libmp3lame", "-b:a", "96k", str(encoded)], + check=True, + ) + for destination in destinations: + shutil.copyfile(encoded, destination) + print(destination.relative_to(root)) + print(f"Radio ringtone: {duration}s, mono {rate}Hz, peak {20 * math.log10(peak):.1f} dBFS") + + +if __name__ == "__main__": + main()