Générateur de fichier .wav à partir d'un fichier .k7 pour Thomson TO7/70.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

177 lines
4.1 KiB

#!/usr/bin/env python
#
# Converts TO7 K7 files into wav file.
#
# History:
# 15/01/2010 Original code by Doug Letougth.
# 16/01/2010 Reworked by Samuel Devulder to speed it up and make it work with
# http://nostalgies.thomsonistes.org/archives/k7tools-2.1a-dosexe.zip
# 17/01/2010 Added a 1sec 6.3khz signal at start of blocks.
# Also added 1sec pause at end of header and end of file block
# (to simulate motor start delay). The resulting file works under MESS.
#
import sys
import os
import wave
import math
import struct
# wav freq
freq = 44100
# number of bits per sample (8 or 16)
nbits = 8
# number of channels (1 = mono, 2 = stereo)
nchans = 1
# transmission rate (bits per seconds)
bps = 900
# relative intensity level for each bit (not necessary but helps reading the curves visualy)
vol0 = 0.9
vol1 = 0.6
# Clear screen (avalibale only on posix systems)
if os.name == "posix":
print "\x1b[1;1H\033[J"
# Some ansi escape characters for verbose display
ansi_esc="\x1b[1;1H"
else:
# No ansi for non-POSIX compliant systems
ansi_esc=""
if len( sys.argv ) != 3 :
exit("Usage : k7towav.py <input .k7 file> <output .wav file>")
else:
input_k7 = sys.argv[1]
output_wav = sys.argv[2]
if not os.path.isfile(input_k7) :
exit("File not found : " + input_k7)
if os.path.isfile(output_wav) :
exit("File already exists : " + output_wav)
# TODO : Add some code here for asking for overwrite
# 2pi
two_pi = 2*math.pi
# length of a bit
samples_per_bit = int(freq / bps)
# 4.5khz signal sample
bit0 = [ math.sin( two_pi*5*x/samples_per_bit ) for x in range(samples_per_bit) ]
# 6.3khz signal sample
bit1 = [ math.sin( two_pi*7*x/samples_per_bit ) for x in range(samples_per_bit) ]
# scale
scale = (2**nbits - 1)/2
# build up string representing the frames for bit0 and bit1 (all channels have the same value).
if nbits==8:
fmt = 'B'
elif nbits==16:
fmt = 'H'
else:
exit("Invalid number of bits: " + str(nbits))
sig_0 = ''
for x in bit0:
for y in range(nchans):
sig_0 += struct.pack(fmt, int(scale*max(0,min(2, 1+x*vol0))))
sig_1 = ''
for x in bit1:
for y in range(nchans):
sig_1 += struct.pack(fmt, int(scale*max(0,min(2, 1+x*vol1))))
# build up strings representing various silence length
inactive_level = 0 # should be -1 according to the docs
silence = ''
for x in range(int(1.00 * freq)):
silence += struct.pack(fmt, int(scale*max(0,min(2, 1+inactive_level))))
start6300 = ''
for x in range(int(1.00 * freq)):
start6300 += struct.pack(fmt, int(scale*max(0,min(2, 1+0.4*math.sin(two_pi * x* 6300/freq)))))
# Bit counter (for display purpose)
bitnum=0
# open files
k7 = open(input_k7,"rb")
wav = wave.open(output_wav,"wb")
wav.setparams((nchans, nbits>>3, freq, 0, 'NONE', 'noncompressed'))
# initial separation
wav.writeframesraw(start6300)
# block state-machine parameters
state = 0
blk_len = None
while 1 :
c = k7.read(1)
if not c:
break
byte = ord(c)
# Start bit is 0
wav.writeframesraw(sig_0)
# Byte processing
acc = byte | 256
while acc != 1:
bitnum=bitnum+1
bit = 1 & acc
acc >>= 1
if bit:
wav.writeframesraw(sig_1)
else:
wav.writeframesraw(sig_0)
if bitnum % 5123 == 0:
print ansi_esc+"Processing bit # "+str(bitnum & 7)+" from byte # "+str(bitnum>>3)+" ("+str(bit)+") "+str(wav.tell()/1024)+" Kbytes"
# Ending bits are 1 (2 bits)
wav.writeframesraw(sig_1)
wav.writeframesraw(sig_1)
# block state machine.
if state==0:
# State 0 to 3 looks for specific block starts that matches (ff ff .. ff 01 3c)
if byte==0xff:
state=1
else:
state=0
elif state==1:
if byte==0xff:
state=1
elif byte==0x01:
state=2
else:
state=0
elif state==2:
if byte==0x3c:
state=3
else:
state=0
elif state==3:
# read block type: 00=header, 01=data, ff=end of file
state=4
blk_type = byte
elif state==4:
# read block length
blk_len = byte
state=5
elif state==5:
# within block
blk_len = blk_len-1
if blk_len<0:
state = 0
# add a sep at end of header block or at end of file block
if blk_type==0 or blk_type==0xff:
wav.writeframesraw(silence)
wav.writeframesraw(start6300)
wav.writeframesraw(silence)
k7.close()
wav.close()