Mercurial > touhou
changeset 325:cddfd3cb4797
Add music support for >PCB.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Thu, 21 Jun 2012 15:01:01 +0200 |
parents | c412df42aa15 |
children | efcdf2ce747c |
files | pytouhou/formats/fmt.py pytouhou/resource/loader.py pytouhou/ui/music.py |
diffstat | 3 files changed, 105 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/pytouhou/formats/fmt.py @@ -0,0 +1,69 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2012 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + + +from struct import unpack + + +class Track(object): + def __init__(self): + self.name = '' + + # loop info + self.intro = 0 + #self.unknown + self.start = 0 + self.duration = 0 + + # WAVE header + self.wFormatTag = 1 + self.wChannels = 2 + self.dwSamplesPerSec = 44100 + self.dwAvgBytesPerSec = 176400 + self.wBlockAlign = 4 + self.wBitsPerSample = 16 + + +class FMT(list): + @classmethod + def read(cls, file): + self = cls() + + file.seek(0) + while True: + track = Track() + track.name = unpack('<16s', file.read(16))[0] + if not ord(track.name[0]): + break + + # loop info + track.intro, unknown, track.start, track.duration = unpack('<IIII', file.read(16)) + + # WAVE header + (track.wFormatTag, + track.wChannels, + track.dwSamplesPerSec, + track.dwAvgBytesPerSec, + track.wBlockAlign, + track.wBitsPerSample) = unpack('<HHLLHH', file.read(16)) + + assert track.wFormatTag == 1 # We don’t support non-PCM formats + assert track.dwAvgBytesPerSec == track.dwSamplesPerSec * track.wBlockAlign + assert track.wBlockAlign == track.wChannels * track.wBitsPerSample // 8 + assert b'\00\00\00\00' == file.read(4) + + self.append(track) + + return self +
--- a/pytouhou/resource/loader.py +++ b/pytouhou/resource/loader.py @@ -25,6 +25,7 @@ from pytouhou.formats.msg import MSG from pytouhou.formats.sht import SHT from pytouhou.formats.exe import SHT as EoSDSHT, InvalidExeException from pytouhou.formats.music import Track +from pytouhou.formats.fmt import FMT from pytouhou.resource.anmwrapper import AnmWrapper @@ -108,6 +109,7 @@ class Loader(object): self.instanced_msgs = {} self.instanced_shts = {} self.instanced_tracks = {} + self.instanced_fmts = {} def scan_archives(self, paths_lists): @@ -194,6 +196,13 @@ class Loader(object): return self.instanced_tracks[name] + def get_fmt(self, name): + if name not in self.instanced_fmts: + file = self.get_file(name) + self.instanced_fmts[name] = FMT.read(file) #TODO: modular + return self.instanced_fmts[name] + + def get_anm_wrapper(self, names, offsets=None): """Create an AnmWrapper for ANM files “names”.
--- a/pytouhou/ui/music.py +++ b/pytouhou/ui/music.py @@ -13,7 +13,7 @@ ## -from pyglet.media import AudioData +from pyglet.media import AudioData, AudioFormat from pyglet.media.riff import WaveSource @@ -51,3 +51,29 @@ class InfiniteWaveSource(WaveSource): duration = float(bytes) / self.audio_format.bytes_per_second return AudioData(data, bytes, timestamp, duration) + + + def seek(self, timestamp): + raise NotImplementedError('irrelevant') + + +class ZwavSource(InfiniteWaveSource): + def __init__(self, filename, format, file=None): + if file is None: + file = open(filename, 'rb') + + self._file = file + + assert b'ZWAV' == self._file.read(4) + + self.audio_format = AudioFormat( + channels=format.wChannels, + sample_size=format.wBitsPerSample, + sample_rate=format.dwSamplesPerSec) + + self._start_offset = 0 + self._offset = format.intro + + self._file.seek(self._offset) + self._start = format.intro + format.start + self._end = format.intro + format.duration