lvthn-codec 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FreshLend Studio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,30 @@
1
+ LVTHN-CODEC — Patent Notice
2
+
3
+ This software is released under the MIT License.
4
+
5
+ The author is not aware of any patents that cover the algorithms implemented
6
+ here. The core techniques used are:
7
+
8
+ Audio:
9
+ - MDCT / IMDCT with sine window (Princen-Bradley, 1986–87; expired)
10
+ - TDAC (Time-Domain Aliasing Cancellation, 1986; expired)
11
+ - Mid/Side stereo coding (Blumlein, 1930s; classic technique)
12
+ - Bark-scale band partitioning (Barkhausen 1960s, public domain)
13
+ - Absolute Threshold of Hearing (Terhardt 1979, public domain)
14
+ - Rice coding (Golomb 1966, Rice 1979; expired)
15
+ - Adaptive per-band quantization (basic idea, expired)
16
+
17
+ Images:
18
+ - Oklab color space (Björn Ottosson, 2020; public domain)
19
+ - Block DCT (discrete cosine transform; expired)
20
+ - Run-Length Encoding (RLE; public domain)
21
+ - Zstandard compression (Yann Collet, 2015; BSD/GPLv2, patent-free)
22
+
23
+ This is NOT a legal guarantee of patent non-infringement. No warranty is
24
+ provided. If you distribute binaries based on this code commercially,
25
+ consult a patent attorney about your jurisdiction.
26
+
27
+ The author has intentionally avoided:
28
+ - Full psychoacoustic masking models identical to MP3/AAC
29
+ - SBR / PS / HE-AAC extensions
30
+ - Any code from FFmpeg, LAME, Opus, Vorbis, or other existing codecs
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: lvthn-codec
3
+ Version: 1.0.0
4
+ Summary: Universal LVTHN media codec: audio (MDCT + Bark + Psy) and images (Oklab + DCT + zstd)
5
+ Author: FreshGame
6
+ Maintainer: FreshLend Studio
7
+ License-Expression: MIT
8
+ Keywords: audio,codec,image,compression,mdct,dct,psychoacoustics,oklab,lvn,patent-free
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Multimedia :: Sound/Audio
16
+ Classifier: Topic :: Multimedia :: Graphics
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ License-File: PATENTS
21
+ Requires-Dist: numpy==2.2.6
22
+ Requires-Dist: scipy==1.15.3
23
+ Requires-Dist: numba==0.68.1
24
+ Requires-Dist: zstandard==0.25.0
25
+ Requires-Dist: Pillow==12.3.0
26
+ Dynamic: license-file
27
+
28
+ # LVTHN-CODEC [RU](README.md) | **EN**
29
+
30
+ A modular, patent-clean, and highly efficient media codec written in Python.
31
+ It uses a universal container (`.lvn`) that supports both **Audio** and **Images**, applying modern psychoacoustic and psychovisual models to outperform industry standards like MP3 and PNG.
32
+
33
+ ## Features
34
+
35
+ * **Universal container (`.lvn`):** One format for everything. The decoder automatically detects what is inside.
36
+ * **Audio codec:** MDCT + Mid/Side stereo + Bark scale bands + Absolute Threshold of Hearing (ATH) + Adaptive quantization.
37
+ * **Image codec:** Oklab color space + Block DCT + RLE + Zstandard.
38
+ * **Performance:**
39
+ * Audio outperforms MP3 in size by **~15%** at the same perceived quality.
40
+ * Images outperform PNG in size by **6 to 7 times** with visually indistinguishable quality.
41
+ * High speed: Audio RTF < 0.02, 4K image decoding takes about 3 seconds.
42
+
43
+ ## Installation
44
+
45
+ Ensure you have Python 3.10+ installed.
46
+
47
+ ```bash
48
+ pip install numpy scipy numba zstandard Pillow sounddevice PySide6
49
+ ```
50
+ *(Note: For `converter.py` to work with formats like MP3 or JPG, you need to install `ffmpeg` and add it to the system PATH environment variable).*
51
+
52
+ ## Usage
53
+
54
+ ### 1. Codec CLI (`codec.py`)
55
+ Direct encoding and decoding to and from the `.lvn` format.
56
+ ```bash
57
+ # Audio
58
+ python codec.py encode track.wav track.lvn compact
59
+ python codec.py decode track.lvn out.wav
60
+
61
+ # Images
62
+ python codec.py encode-img image.png image.lvn fast
63
+ python codec.py decode-img image.lvn out.png
64
+
65
+ # File info
66
+ python codec.py info track.lvn
67
+ ```
68
+
69
+ ### 2. Converter (`converter.py`)
70
+ Converts any supported format (via ffmpeg) to `.lvn` and back.
71
+ ```bash
72
+ python converter.py to-lvn track.mp3 track.lvn --profile default
73
+ python converter.py from-lvn track.lvn track_out.mp3 --bitrate 192k
74
+ ```
75
+
76
+ ### 3. Player (`player.py`)
77
+ Modern GUI player and image viewer based on PySide6.
78
+ ```bash
79
+ python player.py track.lvn
80
+ python player.py image.lvn
81
+ ```
82
+
83
+ ### 4. Benchmark (`benchmark.py`)
84
+ Testing speed and compression ratio on your files.
85
+ ```bash
86
+ python benchmark.py --audio audio.wav --image image.png --image-profiles fast max
87
+ ```
88
+
89
+ ## Profiles
90
+
91
+ ### Audio Profiles
92
+ | Profile | Description | SNR | Best for |
93
+ |---|---|---|---|
94
+ | `compact` | Maximum compression | 20.0 | Everyday listening, saving space |
95
+ | `default` | Balanced | 24.0 | High-quality music |
96
+ | `speech` | Voice optimized | 20.0 | Podcasts, audiobooks |
97
+ | `detail` | Preserves quiet details | 24.0 | Lo-Fi, acoustic, vinyl |
98
+ | `master` | Archival quality | 30.0 | Mastering, studio archives |
99
+
100
+ ### Image Profiles
101
+ | Profile | Quality | Zstd Level | Best for |
102
+ |---|---|---|---|
103
+ | `fast` | 85 | 1 | Quick preview, game textures |
104
+ | `default` | 92 | 12 | Web images, everyday use |
105
+ | `max` | 98 | 19 | Archiving, professional photography |
106
+
107
+ ## Benchmarks
108
+
109
+ ### Audio (179 sec track)
110
+ | File | Profile | Bitrate | SNR | Enc RTF | Dec RTF | Compression |
111
+ |---|---|---|---|---|---|---|
112
+ | acoustic.wav | compact | 113 kbps | 27.5 dB | 0.022 | 0.009 | 13.5x |
113
+ | acoustic.wav | master | 225 kbps | 40.8 dB | 0.020 | 0.010 | 6.8x |
114
+
115
+ ### Images (4K 8.29 MP)
116
+ | File | Profile | PSNR | Enc Time | Dec Time | Compression |
117
+ |---|---|---|---|---|---|
118
+ | 4k_image.png | fast | 42.1 dB | 4.10s | 3.14s | 7.1x |
119
+ | 4k_image.png | max | 48.3 dB | 29.32s | 3.14s | 4.3x |
120
+
121
+ *(PSNR > 40 dB is considered visually indistinguishable from the original. RTF < 1.0 means faster than real time).*
122
+
123
+ ## Architecture
124
+
125
+ * `codec.py` - Main CLI and API.
126
+ * `core/container.py` - Universal LVTHN wrapper.
127
+ * `core/audio.py` - Audio math (MDCT, Bark, Psy).
128
+ * `core/image.py` - Image math (Oklab, DCT).
129
+ * `player.py` - GUI (PySide6).
130
+ * `converter.py` - FFmpeg wrapper.
131
+ * `benchmark.py` - Performance testing tool.
132
+
133
+ ## License and Patents
134
+
135
+ The project is distributed under the **MIT** license.
136
+ It is built exclusively on patent-free algorithms (MDCT, Oklab, DCT, Rice coding, Zstandard). See the `PATENTS` file for a detailed breakdown.
@@ -0,0 +1,109 @@
1
+ # LVTHN-CODEC [RU](README.md) | **EN**
2
+
3
+ A modular, patent-clean, and highly efficient media codec written in Python.
4
+ It uses a universal container (`.lvn`) that supports both **Audio** and **Images**, applying modern psychoacoustic and psychovisual models to outperform industry standards like MP3 and PNG.
5
+
6
+ ## Features
7
+
8
+ * **Universal container (`.lvn`):** One format for everything. The decoder automatically detects what is inside.
9
+ * **Audio codec:** MDCT + Mid/Side stereo + Bark scale bands + Absolute Threshold of Hearing (ATH) + Adaptive quantization.
10
+ * **Image codec:** Oklab color space + Block DCT + RLE + Zstandard.
11
+ * **Performance:**
12
+ * Audio outperforms MP3 in size by **~15%** at the same perceived quality.
13
+ * Images outperform PNG in size by **6 to 7 times** with visually indistinguishable quality.
14
+ * High speed: Audio RTF < 0.02, 4K image decoding takes about 3 seconds.
15
+
16
+ ## Installation
17
+
18
+ Ensure you have Python 3.10+ installed.
19
+
20
+ ```bash
21
+ pip install numpy scipy numba zstandard Pillow sounddevice PySide6
22
+ ```
23
+ *(Note: For `converter.py` to work with formats like MP3 or JPG, you need to install `ffmpeg` and add it to the system PATH environment variable).*
24
+
25
+ ## Usage
26
+
27
+ ### 1. Codec CLI (`codec.py`)
28
+ Direct encoding and decoding to and from the `.lvn` format.
29
+ ```bash
30
+ # Audio
31
+ python codec.py encode track.wav track.lvn compact
32
+ python codec.py decode track.lvn out.wav
33
+
34
+ # Images
35
+ python codec.py encode-img image.png image.lvn fast
36
+ python codec.py decode-img image.lvn out.png
37
+
38
+ # File info
39
+ python codec.py info track.lvn
40
+ ```
41
+
42
+ ### 2. Converter (`converter.py`)
43
+ Converts any supported format (via ffmpeg) to `.lvn` and back.
44
+ ```bash
45
+ python converter.py to-lvn track.mp3 track.lvn --profile default
46
+ python converter.py from-lvn track.lvn track_out.mp3 --bitrate 192k
47
+ ```
48
+
49
+ ### 3. Player (`player.py`)
50
+ Modern GUI player and image viewer based on PySide6.
51
+ ```bash
52
+ python player.py track.lvn
53
+ python player.py image.lvn
54
+ ```
55
+
56
+ ### 4. Benchmark (`benchmark.py`)
57
+ Testing speed and compression ratio on your files.
58
+ ```bash
59
+ python benchmark.py --audio audio.wav --image image.png --image-profiles fast max
60
+ ```
61
+
62
+ ## Profiles
63
+
64
+ ### Audio Profiles
65
+ | Profile | Description | SNR | Best for |
66
+ |---|---|---|---|
67
+ | `compact` | Maximum compression | 20.0 | Everyday listening, saving space |
68
+ | `default` | Balanced | 24.0 | High-quality music |
69
+ | `speech` | Voice optimized | 20.0 | Podcasts, audiobooks |
70
+ | `detail` | Preserves quiet details | 24.0 | Lo-Fi, acoustic, vinyl |
71
+ | `master` | Archival quality | 30.0 | Mastering, studio archives |
72
+
73
+ ### Image Profiles
74
+ | Profile | Quality | Zstd Level | Best for |
75
+ |---|---|---|---|
76
+ | `fast` | 85 | 1 | Quick preview, game textures |
77
+ | `default` | 92 | 12 | Web images, everyday use |
78
+ | `max` | 98 | 19 | Archiving, professional photography |
79
+
80
+ ## Benchmarks
81
+
82
+ ### Audio (179 sec track)
83
+ | File | Profile | Bitrate | SNR | Enc RTF | Dec RTF | Compression |
84
+ |---|---|---|---|---|---|---|
85
+ | acoustic.wav | compact | 113 kbps | 27.5 dB | 0.022 | 0.009 | 13.5x |
86
+ | acoustic.wav | master | 225 kbps | 40.8 dB | 0.020 | 0.010 | 6.8x |
87
+
88
+ ### Images (4K 8.29 MP)
89
+ | File | Profile | PSNR | Enc Time | Dec Time | Compression |
90
+ |---|---|---|---|---|---|
91
+ | 4k_image.png | fast | 42.1 dB | 4.10s | 3.14s | 7.1x |
92
+ | 4k_image.png | max | 48.3 dB | 29.32s | 3.14s | 4.3x |
93
+
94
+ *(PSNR > 40 dB is considered visually indistinguishable from the original. RTF < 1.0 means faster than real time).*
95
+
96
+ ## Architecture
97
+
98
+ * `codec.py` - Main CLI and API.
99
+ * `core/container.py` - Universal LVTHN wrapper.
100
+ * `core/audio.py` - Audio math (MDCT, Bark, Psy).
101
+ * `core/image.py` - Image math (Oklab, DCT).
102
+ * `player.py` - GUI (PySide6).
103
+ * `converter.py` - FFmpeg wrapper.
104
+ * `benchmark.py` - Performance testing tool.
105
+
106
+ ## License and Patents
107
+
108
+ The project is distributed under the **MIT** license.
109
+ It is built exclusively on patent-free algorithms (MDCT, Oklab, DCT, Rice coding, Zstandard). See the `PATENTS` file for a detailed breakdown.
@@ -0,0 +1,109 @@
1
+ # LVTHN-CODEC **RU** | [EN](README.EN.md)
2
+
3
+ Модульный, патентно-чистый и высокоэффективный медиа-кодек, написанный на Python.
4
+ Он использует универсальный контейнер (`.lvn`), который поддерживает как **Аудио**, так и **Изображения**, применяя современные психоакустические и психовизуальные модели, чтобы превзойти промышленные стандарты вроде MP3 и PNG.
5
+
6
+ ## Особенности
7
+
8
+ * **Универсальный контейнер (`.lvn`):** Один формат для всего. Декодер автоматически определяет, что внутри.
9
+ * **Аудиокодек:** MDCT + Mid/Side стерео + полосы Барка + Абсолютный порог слышимости (ATH) + Адаптивное квантование.
10
+ * **Кодек изображений:** Цветовое пространство Oklab + Блочный DCT + RLE + Zstandard.
11
+ * **Производительность:**
12
+ * Аудио превосходит MP3 по размеру на **~15%** при том же воспринимаемом качестве.
13
+ * Изображения превосходят PNG по размеру в **6-7 раз** при визуально неотличимом качестве.
14
+ * Высокая скорость: RTF аудио < 0.02, декодирование 4К-картинки ~3 секунды.
15
+
16
+ ## Установка
17
+
18
+ Убедитесь, что у вас установлен Python 3.10+.
19
+
20
+ ```bash
21
+ pip install numpy scipy numba zstandard Pillow sounddevice PySide6
22
+ ```
23
+ *(Примечание: Для работы `converter.py` с форматами вроде MP3 или JPG необходимо установить `ffmpeg` и добавить его в системную переменную PATH).*
24
+
25
+ ## Использование
26
+
27
+ ### 1. CLI кодек (`codec.py`)
28
+ Прямое кодирование и декодирование в/из формата `.lvn`.
29
+ ```bash
30
+ # Аудио
31
+ python codec.py encode track.wav track.lvn compact
32
+ python codec.py decode track.lvn out.wav
33
+
34
+ # Изображения
35
+ python codec.py encode-img image.png image.lvn fast
36
+ python codec.py decode-img image.lvn out.png
37
+
38
+ # Информация о файле
39
+ python codec.py info track.lvn
40
+ ```
41
+
42
+ ### 2. Конвертер (`converter.py`)
43
+ Конвертирует любые поддерживаемые форматы (через ffmpeg) в `.lvn` и обратно.
44
+ ```bash
45
+ python converter.py to-lvn track.mp3 track.lvn --profile default
46
+ python converter.py from-lvn track.lvn track_out.mp3 --bitrate 192k
47
+ ```
48
+
49
+ ### 3. Плеер (`player.py`)
50
+ Современный GUI-плеер и просмотрщик картинок на PySide6.
51
+ ```bash
52
+ python player.py track.lvn
53
+ python player.py image.lvn
54
+ ```
55
+
56
+ ### 4. Бенчмарк (`benchmark.py`)
57
+ Тестирование скорости и степени сжатия на ваших файлах.
58
+ ```bash
59
+ python benchmark.py --audio audio.wav --image image.png --image-profiles fast max
60
+ ```
61
+
62
+ ## Профили
63
+
64
+ ### Профили аудио
65
+ | Профиль | Описание | SNR | Для чего лучше всего |
66
+ |---------|-------------|-----|----------|
67
+ | `compact` | Максимальное сжатие | 20.0 | Повседневное прослушивание, экономия места |
68
+ | `default` | Сбалансированный | 24.0 | Музыка высокого качества |
69
+ | `speech` | Оптимизация под голос | 20.0 | Подкасты, аудиокниги |
70
+ | `detail` | Сохраняет тихие детали | 24.0 | Lo-Fi, акустика, винил |
71
+ | `master` | Архивное качество | 30.0 | Мастеринг, студийные архивы |
72
+
73
+ ### Профили изображений
74
+ | Профиль | Качество | Уровень Zstd | Для чего лучше всего |
75
+ |---------|---------|------------|----------|
76
+ | `fast` | 85 | 1 | Быстрый просмотр, текстуры для игр |
77
+ | `default` | 92 | 12 | Картинки для веба, повседневное использование |
78
+ | `max` | 98 | 19 | Архивация, профессиональная фотография |
79
+
80
+ ## Бенчмарки
81
+
82
+ ### Аудио (трек 179 сек)
83
+ | Файл | Профиль | Битрейт | SNR | Enc RTF | Dec RTF | Сжатие |
84
+ |---|---|---|---|---|---|---|
85
+ | acoustic.wav | compact | 113 kbps | 27.5 dB | 0.022 | 0.009 | 13.5x |
86
+ | acoustic.wav | master | 225 kbps | 40.8 dB | 0.020 | 0.010 | 6.8x |
87
+
88
+ ### Изображения (4K 8.29 Мп)
89
+ | Файл | Профиль | PSNR | Время Enc | Время Dec | Сжатие |
90
+ |---|---|---|---|---|---|
91
+ | 4k_image.png | fast | 42.1 dB | 4.10s | 3.14s | 7.1x |
92
+ | 4k_image.png | max | 48.3 dB | 29.32s | 3.14s | 4.3x |
93
+
94
+ *(PSNR > 40 dB считается визуально неотличимым от оригинала. RTF < 1.0 означает работу быстрее реального времени).*
95
+
96
+ ## Архитектура
97
+
98
+ * `codec.py` - Основной CLI и API.
99
+ * `core/container.py` - Универсальная обёртка LVTHN.
100
+ * `core/audio.py` - Математика аудио (MDCT, Bark, Psy).
101
+ * `core/image.py` - Математика изображений (Oklab, DCT).
102
+ * `player.py` - Графический интерфейс (PySide6).
103
+ * `converter.py` - Обёртка над FFmpeg.
104
+ * `benchmark.py` - Инструмент тестирования производительности.
105
+
106
+ ## Лицензия и Патенты
107
+
108
+ Проект распространяется под лицензией **MIT**.
109
+ Он построен исключительно на алгоритмах, свободных от патентов (MDCT, Oklab, DCT, Rice coding, Zstandard). Подробный разбор смотрите в файле `PATENTS`.
@@ -0,0 +1,149 @@
1
+ import sys
2
+ import time
3
+ from pathlib import Path
4
+ import numpy as np
5
+ from scipy.io import wavfile
6
+
7
+ from core import container, audio, image
8
+
9
+ PROFILES = {
10
+ 'default': {'delta': 0.18, 'snr': 24.0},
11
+ 'compact': {'delta': 0.25, 'snr': 20.0},
12
+ 'detail': {'delta': 0.05, 'snr': 24.0},
13
+ 'speech': {'delta': 0.10, 'snr': 20.0},
14
+ 'master': {'delta': 0.03, 'snr': 30.0},
15
+ }
16
+
17
+ IMG_PROFILES = {
18
+ 'fast': {'quality': 85, 'level': 1},
19
+ 'default': {'quality': 92, 'level': 12},
20
+ 'max': {'quality': 98, 'level': 19},
21
+ }
22
+
23
+ def encode_pcm(pcm, sr, ch, delta, target_snr_db):
24
+ payload = audio.encode_audio(pcm, sr, ch, delta, target_snr_db)
25
+ return container.wrap(container.MEDIA_AUDIO, payload)
26
+
27
+ def decode_lvn(data):
28
+ media_type, payload = container.unwrap(data)
29
+ if media_type == container.MEDIA_AUDIO:
30
+ return audio.decode_audio(payload)
31
+ elif media_type == container.MEDIA_IMAGE:
32
+ return image.decode_image(payload)
33
+ else:
34
+ raise ValueError(f'Unsupported media_type: 0x{media_type:02x}')
35
+
36
+ def decode_lvn_info(data):
37
+ media_type, payload = container.unwrap(data)
38
+ if media_type == container.MEDIA_AUDIO:
39
+ info = audio.get_audio_info(payload)
40
+ info['media_type'] = media_type
41
+ info['total'] = len(data)
42
+ return info
43
+ elif media_type == container.MEDIA_IMAGE:
44
+ info = image.get_image_info(payload)
45
+ info['media_type'] = media_type
46
+ info['total'] = len(data)
47
+ return info
48
+ return dict(media_type=media_type, total=len(data))
49
+
50
+ def read_wav(path):
51
+ sr, d = wavfile.read(path)
52
+ if d.dtype == np.int16: d = d.astype(np.float64) / 32768.0
53
+ elif d.dtype == np.int32: d = d.astype(np.float64) / 2147483648.0
54
+ elif d.dtype == np.uint8: d = (d.astype(np.float64) - 128.0) / 128.0
55
+ else: d = d.astype(np.float64)
56
+ if d.ndim == 1: d = d[:, None]
57
+ return d, sr
58
+
59
+ def write_wav(path, pcm, sr):
60
+ wavfile.write(path, sr, np.clip(pcm * 32767, -32768, 32767).astype(np.int16))
61
+
62
+ def read_image(path):
63
+ from PIL import Image
64
+ img = Image.open(path)
65
+ if img.mode == 'RGBA':
66
+ return np.array(img), 4
67
+ else:
68
+ return np.array(img.convert('RGB')), 3
69
+
70
+ def write_image(path, pixels, channels):
71
+ from PIL import Image
72
+ img = Image.fromarray(pixels)
73
+ img.save(path)
74
+
75
+ def main():
76
+ if len(sys.argv) < 2:
77
+ print('LVTHN-CODEC')
78
+ print('Commands: encode | decode | info | encode-img | decode-img | profiles')
79
+ sys.exit(1)
80
+ cmd, args = sys.argv[1], sys.argv[2:]
81
+
82
+ if cmd == 'encode':
83
+ if len(args) < 2: sys.exit('usage: encode in.wav out.lvn [profile|delta] [target_snr_db]')
84
+ pcm, sr = read_wav(args[0])
85
+ arg2 = args[2] if len(args) > 2 else 'default'
86
+ if arg2 in PROFILES:
87
+ delta = PROFILES[arg2]['delta']
88
+ tsnr = PROFILES[arg2]['snr']
89
+ print(f'[audio profile: {arg2}] delta={delta} snr={tsnr}')
90
+ else:
91
+ delta = float(arg2)
92
+ tsnr = float(args[3]) if len(args) > 3 else 24.0
93
+
94
+ t0 = time.time()
95
+ data = encode_pcm(pcm, sr, pcm.shape[1], delta, target_snr_db=tsnr)
96
+ Path(args[1]).write_bytes(data)
97
+ print(f'OK {args[1]} {len(data)} bytes ({pcm.size * 2 / len(data):.2f}x vs PCM) encode={time.time() - t0:.2f}s')
98
+
99
+ elif cmd == 'decode':
100
+ if len(args) < 2: sys.exit('usage: decode in.lvn out.wav')
101
+ pcm, sr, ch, n = decode_lvn(Path(args[0]).read_bytes())
102
+ write_wav(args[1], pcm, sr)
103
+ print(f'OK {args[1]} {n} samples, {ch} ch, {sr} Hz')
104
+
105
+ elif cmd == 'encode-img':
106
+ if len(args) < 2: sys.exit('usage: encode-img in.png out.lvn [profile|quality] [level]')
107
+ pixels, ch = read_image(args[0])
108
+ arg2 = args[2] if len(args) > 2 else 'default'
109
+ if arg2 in IMG_PROFILES:
110
+ q = IMG_PROFILES[arg2]['quality']
111
+ lvl = IMG_PROFILES[arg2]['level']
112
+ print(f'[image profile: {arg2}] quality={q} level={lvl}')
113
+ else:
114
+ q = int(arg2)
115
+ lvl = int(args[3]) if len(args) > 3 else 19
116
+
117
+ t0 = time.time()
118
+ payload = image.encode_image(pixels, pixels.shape[1], pixels.shape[0], ch, q, lvl)
119
+ data = container.wrap(container.MEDIA_IMAGE, payload)
120
+ Path(args[1]).write_bytes(data)
121
+ print(f'OK {args[1]} {len(data)} bytes encode={time.time() - t0:.2f}s')
122
+
123
+ elif cmd == 'decode-img':
124
+ if len(args) < 2: sys.exit('usage: decode-img in.lvn out.png')
125
+ mt, payload = container.unwrap(Path(args[0]).read_bytes())
126
+ if mt != container.MEDIA_IMAGE: sys.exit('Not an image')
127
+ pixels = image.decode_image(payload)
128
+ write_image(args[1], pixels, pixels.shape[2] if len(pixels.shape) > 2 else 1)
129
+ print(f'OK {args[1]}')
130
+
131
+ elif cmd == 'info':
132
+ if not args: sys.exit('usage: info file.lvn')
133
+ info = decode_lvn_info(Path(args[0]).read_bytes())
134
+ if info['media_type'] == container.MEDIA_AUDIO:
135
+ print(f"LVTHN v1 audio {info['sr']} Hz {info['ch']} ch {info['n_samples'] / info['sr']:.2f}s delta={info['delta']:.4f}")
136
+ print(f" target_snr_db: {info['target_snr_db']:.1f} use_ms: {info['use_ms']} total: {info['total']}")
137
+ elif info['media_type'] == container.MEDIA_IMAGE:
138
+ print(f"LVTHN v1 image {info['width']}x{info['height']} alpha={info['has_alpha']} quality={info['quality']:.0f} total: {info['total']}")
139
+
140
+ elif cmd == 'profiles':
141
+ print('Audio profiles:')
142
+ for name, p in PROFILES.items():
143
+ print(f' {name:10s} delta={p["delta"]:<6} snr={p["snr"]}')
144
+ print('Image profiles:')
145
+ for name, p in IMG_PROFILES.items():
146
+ print(f' {name:10s} quality={p["quality"]:<4} level={p["level"]}')
147
+
148
+ if __name__ == '__main__':
149
+ main()
File without changes