| bits | 2 ^ bits | dB (power) | dB (amplitude) |
|---|---|---|---|
| 1 | 2 | 3.01 | 6.02 |
| 2 | 4 | 6.02 | 12.04 |
| 3 | 8 | 9.03 | 18.06 |
| 4 | 16 | 12.04 | 24.08 |
| 5 | 32 | 15.05 | 30.10 |
| 6 | 64 | 18.06 | 36.12 |
| import math | |
| def print_audio_frames(num_samples, freq_hz, sample_rate_hz, num_channels): | |
| for i in range(num_samples): | |
| a = math.sin(2 * math.pi * freq_hz * i / sample_rate_hz) | |
| print(f'{i // num_channels:4d} => ', end='') | |
| for j in range(num_channels): | |
| value = ((1 << (15 - j)) - 1) * a; | |
| print(f'{int(value):6d}', end='') | |
| print() |
You need to have [mpv][mpv] installed. For example, you can run brew install mpv for that.
Run the built-in [Automator][automator] app and create a new "Quick Action". Name it "Play in mpv" and set it up according to the screenshot below:
- Workflow receives current
files or foldersinany application - Input is
entire selection - Image
▶ Play
| import argparse | |
| import hashlib | |
| import math | |
| import struct | |
| import wave | |
| def rms(samples): | |
| return math.sqrt(sum(s*s for s in samples) / len(samples)) | |
| def md5(data): |
| #!/bin/bash | |
| osascript -l JavaScript > $(date '+%Y.%m.%d-%H.%M.%S')-chrome-tabs.json <<EOF | |
| var app = Application('Google Chrome'); | |
| let result = app.windows().map((w) => { | |
| return { | |
| 'name': w.name(), | |
| 'tabs': w.tabs().map((t) => { | |
| return {'title': t.title(), 'url': t.url()}; |
| from math import degrees, radians, tan, atan, sqrt | |
| # Diagonal FOV | |
| dfov = 90 | |
| # Sensor size | |
| width, height = 4032, 3024 | |
| r = width / height | |
| # Horizontal FOV (corresponds to width) | |
| hfov = degrees(2 * atan(tan(radians(dfov / 2)) / sqrt(1 + 1 / (r*r)))) | |
| # Vertial FOV (corresponds to height) |
| import argparse | |
| from PIL import Image | |
| def nv12_to_rgb(nv12: bytes | bytearray, size: tuple[int, int]) -> Image: | |
| w, h = size | |
| n = w * h | |
| y, u, v = nv12[:n], nv12[n + 0::2], nv12[n + 1::2] | |
| yuv = bytearray(3 * n) | |
| yuv[0::3] = y | |
| yuv[1::3] = Image.frombytes('L', (w // 2, h // 2), u).resize(size).tobytes() |
The Python argparse module lacks a built-in mechanism for validating
argument ranges. For instance, while you can specify an argument type as int, there is no straightforward way to
restrict it to only positive values. Similarly, when dealing with float arguments, there is no native method to
ensure that the provided values fall within the range of [0.0, 1.0).
CheckRange is a possible solution to this problem. It is a subclass of argparse.Action.
It allows you to validate open, closed, and half-open intervals. Each endpoint can be either a number or positive or negative infinity:
- [a, b] →
min=a, max=b
| set -e | |
| if [[ -f /.dockerenv ]]; then | |
| exit 1 | |
| fi | |
| readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| readonly DOCKER_IMAGE_TAG=$(docker build --quiet - <<EOF | |
| FROM debian:bullseye |
| import argparse | |
| import wave | |
| def crop(src_filename, dst_filename, num_frames): | |
| with wave.open(src_filename, 'rb') as src: | |
| with wave.open(dst_filename, 'wb') as dst: | |
| dst.setnchannels(src.getnchannels()) | |
| dst.setsampwidth(src.getsampwidth()) | |
| dst.setframerate(src.getframerate()) |