aboutsummaryrefslogtreecommitdiff
path: root/examples/sound/spustream/convert_stream.py
diff options
context:
space:
mode:
authorspicyjpeg <thatspicyjpeg@gmail.com>2022-10-27 16:55:08 +0200
committerspicyjpeg <thatspicyjpeg@gmail.com>2022-10-27 16:55:08 +0200
commitf6c41f3783c4fce49a9899b710ebb50ba9f647ab (patch)
tree7133d4e05008cb11c05995d3c0ce7d938258cd51 /examples/sound/spustream/convert_stream.py
parent4dbf47f129a55428b90df2805228fbd481e1d117 (diff)
downloadpsn00bsdk-f6c41f3783c4fce49a9899b710ebb50ba9f647ab.tar.gz
Refactor sound examples, add new spustream example
Diffstat (limited to 'examples/sound/spustream/convert_stream.py')
-rw-r--r--examples/sound/spustream/convert_stream.py112
1 files changed, 0 insertions, 112 deletions
diff --git a/examples/sound/spustream/convert_stream.py b/examples/sound/spustream/convert_stream.py
deleted file mode 100644
index 1b1696f..0000000
--- a/examples/sound/spustream/convert_stream.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env python3
-# Simple .VAG to STREAM.BIN interleaving tool
-# (C) 2021 spicyjpeg - MPL licensed
-
-import sys
-from warnings import warn
-from struct import Struct
-from itertools import zip_longest
-from argparse import ArgumentParser, FileType
-
-VAG_HEADER = Struct("> 4s I 4x 2I 12x 16s")
-VAG_MAGIC = b"VAGp"
-SAMPLE_RATE = 44100
-BUFFER_SIZE = 26624 # (26624 / 16 * 28) / 44100 = 1.05 seconds
-ALIGN_SIZE = 2048
-
-## Helpers
-
-def align(data, size):
- chunks = (len(data) + size - 1) // size
-
- return data.ljust(chunks * size, b"\x00")
-
-def set_loop_flag(data):
- last_block = bytearray(data[-16:])
- last_block[1] = 0x03 # Jump to loop point + sustain
-
- return data[:-16] + last_block
-
-## .VAG file reader
-
-def read_vag(_file, chunk_size):
- with _file:
- header = _file.read(VAG_HEADER.size)
- (
- magic,
- version,
- size,
- sample_rate,
- name
- ) = VAG_HEADER.unpack(header)
-
- #if magic != VAG_MAGIC:
- #raise RuntimeError(f"{_file.name} is not a valid .VAG file")
- if sample_rate != SAMPLE_RATE:
- warn(RuntimeWarning(f"{_file.name} sample rate is not {SAMPLE_RATE} Hz"))
-
- for i in range(0, size, chunk_size):
- chunk = _file.read(chunk_size)
-
- if len(chunk) % 16:
- warn(RuntimeWarning(f"{_file.name} is not 16-byte aligned, trimming"))
- chunk = chunk[0:len(chunk) // 16 * 16]
-
- chunk = set_loop_flag(chunk)
-
- yield chunk.ljust(chunk_size, b"\x00")
-
-## Main
-
-def get_args():
- parser = ArgumentParser(
- description = "Generates interleaved stream data from one or more .VAG files."
- )
- parser.add_argument(
- "input_file",
- nargs = "+",
- type = FileType("rb"),
- help = f"mono input files for each channel (must be {SAMPLE_RATE} Hz .VAG)"
- )
- parser.add_argument(
- "-o", "--output",
- type = FileType("wb"),
- default = "stream.bin",
- help = "where to output converted stream data (stream.bin by default)",
- metavar = "file"
- )
- parser.add_argument(
- "-b", "--buffer-size",
- type = int,
- default = BUFFER_SIZE,
- help = f"size of each interleaved chunk (one per channel, default {BUFFER_SIZE})",
- metavar = "bytes"
- )
- parser.add_argument(
- "-a", "--align",
- type = int,
- default = ALIGN_SIZE,
- help = f"align each group of chunks to N bytes (default {ALIGN_SIZE})",
- metavar = "bytes"
- )
-
- return parser.parse_args()
-
-def main():
- args = get_args()
- if args.buffer_size % 16:
- raise ValueError("buffer size must be a multiple of 16 bytes")
-
- interleave = zip_longest(
- *( read_vag(_file, args.buffer_size) for _file in args.input_file ),
- fillvalue = b"\x00" * args.buffer_size
- )
-
- with args.output as _file:
- for chunks in interleave:
- data = b"".join(chunks)
-
- _file.write(align(data, args.align))
-
-if __name__ == "__main__":
- main()