Anonymous Anonymous - 3 months ago
480 0

A simple command-line script used to extract and display time and date of wav-file recording, produced by Olympus DVR (like VN-480PC) and transferred by Olympus Digital Wave Player software.

Python

Olympus DVR recording date and time extractor

#!/bin/python
"""
A simple Python 2.7 script that parses wav file produced by Olympus Digital Wave Player 
and prints that recording creation time and date.
Input: wav file name as command-line parameter.
Output: recording time and date in format "day.month.year hour:min:sec" or error message

Technical details:
Recording creation time and date is stored in a special chunk, composed as follows.
Chunk header (4 bytes): always "cd  ", note the padding
Chunk data size (4 bytes): always "12", stored as little-endian unsigned integer
Actual chunk data (12 bytes): 6 unsigned byte values, representing year, month, day, hour, minute, second of recording;
and 6-byte value of unknown purpose. Year is the number of years after 2000.

axf 2018
"""

import os
import sys
import struct
import datetime

def seek_to_chunk_data(file, chunkName):
  """Seeks file to chunk named chunkName and returns chunk data size. On error returns -1."""
  FILE_HEADER_SIZE = 12
  file.seek(FILE_HEADER_SIZE, os.SEEK_SET)
  while True:
    CHUNK_HEADER_SIZE = 8
    chunkHeader = file.read(CHUNK_HEADER_SIZE)
    if len(chunkHeader) < CHUNK_HEADER_SIZE:
      raise IOError, "Chunk not found: '{}'".format(chunkName)
    CHUNK_HEADER_FMT = "<4sI"
    name, size = struct.unpack(CHUNK_HEADER_FMT, chunkHeader)
    if chunkName == name:
      return size
    else:
      file.seek(size, os.SEEK_CUR)

def parse_cd_chunk_data(data):
  """Parses cd chunk data and returns dictionary containing recording creation date and time."""
  assert(len(data) == 0xC)
  CD_CHUNK_DATA_FMT = "6B6s"
  unpacked = struct.unpack(CD_CHUNK_DATA_FMT, data)
  kwords = ("y", "m", "d", "hr", "min", "sec", "unknown")
  r = dict(zip(kwords, unpacked))
  r["y"] += 2000
  return r

def run():
  if len(sys.argv) < 2:
    print "Usage: {} file".format(sys.argv[0])
    return 1

  parsedData = None
  try:
    fname = sys.argv[1]
    with open(fname, "rb") as f:
      CD_CHUNK_HEADER_FMT = "\x63\x64\x20\x20" #"cd  "
      size = seek_to_chunk_data(f, CD_CHUNK_HEADER_FMT)
      CD_CHUNK_DATA_SIZE = 0xC
      if size != CD_CHUNK_DATA_SIZE: \
        raise IOError, "Bad chunk data size, expected {}, got {}".format(CD_CHUNK_DATA_SIZE, size)
      rawData = f.read(size)
      parsedData = parse_cd_chunk_data(rawData)
  except IOError as e:
    print e
    return 2

  assert(parsedData is not None)
  values = (parsedData["y"], parsedData["m"], parsedData["d"], parsedData["hr"], parsedData["min"], parsedData["sec"])
  cdDateTime = datetime.datetime(*values)

  fmt = "%d.%m.%Y %H:%M:%S"
  cdTime = ("{:"+fmt+"}").format(cdDateTime)
  print "{}".format(cdTime)

  return 0

if __name__ == "__main__":
  exit(run())
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download