-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathfspeed.py
More file actions
executable file
·153 lines (124 loc) · 5.02 KB
/
fspeed.py
File metadata and controls
executable file
·153 lines (124 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env python3
import struct
import wave
import click
import os
import logging as log
# with some settings it may be needed to change the pitch of the original file
# to balance compression with correct pitch
# note which is used when representing pcm
# this doesn't seem change the output wav at all
NOTE = "c1"
# the length of each note which represents a sample
# also doesn't seem to affect the wav file
NOTE_LENGTH = "f"
# any fsound data to be added at the end of each note
APPEND_DATA = "\n"
# loops each note write by this number
# affects quality and pitch
NOTE_LOOP = 1
# base 2 number, used to determine how many samples are taken from
# the original pcm data
ITER_SAMPLE = 2
# function to run when executing fspeed normally
@click.command()
@click.option('--sample-limit', default=100, help=
"The amount of empty samples needed \
in a row for them to be compressed (default: 100)")
@click.argument('wavfile', type=click.Path(exists=True))
@click.argument('outfile', required=False)
def wav2fss(sample_limit, wavfile, outfile=None):
try:
with wave.open(wavfile, 'rb') as wr:
frames = wr.readframes(wr.getnframes())
except wave.Error as e:
log.error(e)
exit()
if not outfile:
file = open(os.path.splitext(wavfile)[0] + ".fss", 'w')
else:
file = open(outfile, 'w')
def dataget(offset):
return abs(struct.unpack_from('<h', frames, offset)[0])
convert(file, len(frames), dataget, sample_limit)
file.close()
#
# external converting function to make it easier to write scripts around fspeed
# e.g. bytebeat to fss, by importing fspeed from another python script
#
# file - python file pointer
# length - number of samples
# dataget - function that takes the offset parameter and returns data
# sample_limit - for empty sample compression, same as wav2fss function
#
def convert(file, length, dataget, sample_limit):
file.write("0\n")
non_zero_counter = 0
offset = 0
while offset < length:
data_new = dataget(offset)
if data_new > 258:
non_zero_counter = 1
if data_new <= 258 and non_zero_counter > 0:
ignore_end = False
if (offset + ITER_SAMPLE) >= length:
continue
_data_new = dataget(offset + 1)
empty_samples = 1
# get number of empty samples while iterating offset
while _data_new <= 258:
if (offset + ITER_SAMPLE) >= length:
ignore_end = True
break
offset += ITER_SAMPLE
_data_new = dataget(offset)
empty_samples += 1
# complete ignore any end rests + end rests which are less than 10
# in length
if not ignore_end and empty_samples > 10:
# write normal rests if there is a low amount of rests
if empty_samples < sample_limit:
for _ in range(0, round(empty_samples / 2)):
file.write("r\n")
else:
# slow down the tempo by a lot and write a lot less rests
file.write("t15\n");
for _ in range(0, round(empty_samples / sample_limit / 2)):
file.write("r\n")
file.write("t0\n");
write_note = ""
if 258 < data_new <= 1027:
write_note = (NOTE + NOTE_LENGTH + "1" + APPEND_DATA)
elif 1027 < data_new <= 1538:
write_note = (NOTE + NOTE_LENGTH + "2" + APPEND_DATA)
elif 1538 < data_new <= 2305:
write_note = (NOTE + NOTE_LENGTH + "3" + APPEND_DATA)
elif 2305 < data_new <= 3071:
write_note = (NOTE + NOTE_LENGTH + "4" + APPEND_DATA)
elif 3071 < data_new <= 3836:
write_note = (NOTE + NOTE_LENGTH + "5" + APPEND_DATA)
elif 3836 < data_new <= 5372:
write_note = (NOTE + NOTE_LENGTH + "6" + APPEND_DATA)
elif 5372 < data_new <= 6908:
write_note = (NOTE + NOTE_LENGTH + "7" + APPEND_DATA)
elif 6908 < data_new <= 8445:
write_note = (NOTE + NOTE_LENGTH + "8" + APPEND_DATA)
elif 8445 < data_new <= 9214:
write_note = (NOTE + NOTE_LENGTH + "9" + APPEND_DATA)
elif 9214 < data_new <= 9471:
write_note = (NOTE + NOTE_LENGTH + "a" + APPEND_DATA)
elif 9471 < data_new <= 10240:
write_note = (NOTE + NOTE_LENGTH + "b" + APPEND_DATA)
elif 10240 < data_new <= 11776:
write_note = (NOTE + NOTE_LENGTH + "c" + APPEND_DATA)
elif 11776 < data_new <= 16640:
write_note = (NOTE + NOTE_LENGTH + "d" + APPEND_DATA)
elif 16640 < data_new <= 20736:
write_note = (NOTE + NOTE_LENGTH + "e" + APPEND_DATA)
elif 20736 < data_new:
write_note = (NOTE + NOTE_LENGTH + APPEND_DATA)
for _ in range(0, NOTE_LOOP):
file.write(write_note)
offset += ITER_SAMPLE
if __name__ == '__main__':
wav2fss()