Created
October 30, 2023 13:50
-
-
Save pjakuszew/9080e5b4fa20be82496dfe8e9511a3d5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # Usage: soco_alarm_sound_dumper.py <alarm_spi_flash_dump_file> | |
| # | |
| # This script reads the sounds from specified Super Soco alarm module | |
| # memory dump and exports them as playable Wave files. | |
| # | |
| # There seems to be a "table of contents" (ToC) at the beginning of | |
| # SPI flash that defines the location and length of each sound. | |
| # Each ToC entry is 8 bytes long, where 4 bytes are the sound offset and | |
| # and next 4 bytes are denoting the length. After the last ToC entry | |
| # there is a value which I couldn't figure out, that's what causes the | |
| # error about current sound offset being greater that last sound's offset. | |
| # | |
| # Sounds I have found in memory dumps from two alarm modules: | |
| # (listed in no particular order) | |
| # - Lock/unlock/startup sound made out of iPhone "Popcorn" alarm tone | |
| # - Lock/unlock/startup featuring the infamous piano jingle startup that | |
| # pissed me so much I started working on this script | |
| # - Lock/unlock/startup bleeps which I presumed to be some old stuff | |
| # that was supposed to be played on a piezoelectric speaker, but then | |
| # I met someone with a '19 TC Max which used these | |
| # - Error tone which can be heard when you keep pressing Start button | |
| # repeatedly | |
| # - Rather long alarm siren that takes a lot of memory space | |
| # - Short alarm siren | |
| # - Shutdown sound | |
| # | |
| # Sound format: Raw PCM frames, 11025Hz framerate, mono. | |
| # On two different alarm modules these sounds were stored on | |
| # a BoyaMicro 25D16ASTIG SPI flash chip that I was able to read using CH341 | |
| # and flashrom utility on Linux. | |
| # | |
| # I'm sharing this because I don't have time nor will to play with this anymore. | |
| import sys | |
| import struct | |
| import wave | |
| sounds = [] | |
| with open(sys.argv[1], 'rb') as f: | |
| for _ in range(16): | |
| chunk = f.read(8) | |
| if len(chunk) < 8: | |
| break | |
| offset, length = struct.unpack('>ii', chunk) | |
| sounds.append((offset, length)) | |
| for i, sound in enumerate(sounds): | |
| f.seek(sound[0]) | |
| if i+1 < len(sounds): | |
| length = sounds[i+1][0] - sound[0] | |
| if length < 0: | |
| print(f"Error: sound{i} offset is greater than sound{i+1} offset") | |
| continue | |
| data = f.read(length) | |
| else: | |
| data = f.read() | |
| with open(f'sound{i}.pcm', 'wb') as raw_file: | |
| raw_file.write(data) | |
| with wave.open(f'sound{i}.wav', 'wb') as sound_file: | |
| sound_file.setnchannels(1) | |
| sound_file.setsampwidth(4) | |
| sound_file.setframerate(11025.0) | |
| sound_file.writeframesraw(data) | |
| for i, sound in enumerate(sounds): | |
| print(f'[sound{i}] Offset: {sound[0]:x}, Length: {sound[1]:x}') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment