View difference between Paste ID: hLJnpPNv and H1G9HKFX
SHOW: | | - or go back to the newest paste.
1
#!/usr/bin/gawk -f
2
# nokia2beeps.tcl - Play an RTTL ringtone file as beeps
3
# Usage: ./nokia2beeps.tcl ringtone_file
4
5
#TODO: imelody
6
#TODO: chord
7
8
BEGIN {
9-
	#http://www.phy.mtu.edu/~suits/notefreqs.html
9+
10
	default_octave = 4
11
	default_beat = 63
12
	base_time = 200000
13
	loop = 3
14
#	option_qwerty_midi = 0
15
#	option_adjust_octave = 1
16
17
	# http://www.phy.mtu.edu/~suits/notefreqs.html
18
	split("\
19
	C0   16.35    C#0  17.32    Db0  17.32    D0   18.35    D#0  19.45    Eb0  19.45	\
20
	E0   20.60    F0   21.83    F#0  23.12    Gb0  23.12    G0   24.50    G#0  25.96	\
21
	Ab0  25.96    A0   27.50    A#0  29.14    Bb0  29.14    B0   30.87    C1   32.70	\
22
	C#1  34.65    Db1  34.65    D1   36.71    D#1  38.89    Eb1  38.89    E1   41.20	\
23
	F1   43.65    F#1  46.25    Gb1  46.25    G1   49.00    G#1  51.91    Ab1  51.91	\
24
	A1   55.00    A#1  58.27    Bb1  58.27    B1   61.74    C2   65.41    C#2  69.30	\
25
	Db2  69.30    D2   73.42    D#2  77.78    Eb2  77.78    E2   82.41    F2   87.31	\
26
	F#2  92.50    Gb2  92.50    G2   98.00    G#2  103.83   Ab2  103.83   A2   110.00	\
27
	A#2  116.54   Bb2  116.54   B2   123.47   C3   130.81   C#3  138.59   Db3  138.59	\
28
	D3   146.83   D#3  155.56   Eb3  155.56   E3   164.81   F3   174.61   F#3  185.00	\
29
	Gb3  185.00   G3   196.00   G#3  207.65   Ab3  207.65   A3   220.00   A#3  233.08	\
30
	Bb3  233.08   B3   246.94   C4   261.63   C#4  277.18   Db4  277.18   D4   293.66	\
31
	D#4  311.13   Eb4  311.13   E4   329.63   F4   349.23   F#4  369.99   Gb4  369.99	\
32
	G4   392.00   G#4  415.30   Ab4  415.30   A4   440.00   A#4  466.16   Bb4  466.16	\
33
	B4   493.88   C5   523.25   C#5  554.37   Db5  554.37   D5   587.33   D#5  622.25	\
34
	Eb5  622.25   E5   659.26   F5   698.46   F#5  739.99   Gb5  739.99   G5   783.99	\
35
	G#5  830.61   Ab5  830.61   A5   880.00   A#5  932.33   Bb5  932.33   B5   987.77	\
36
	C6   1046.50  C#6  1108.73  Db6  1108.73  D6   1174.66  D#6  1244.51  Eb6  1244.51	\
37
	E6   1318.51  F6   1396.91  F#6  1479.98  Gb6  1479.98  G6   1567.98  G#6  1661.22	\
38
	Ab6  1661.22  A6   1760.00  A#6  1864.66  Bb6  1864.66  B6   1975.53  C7   2093.00	\
39
	C#7  2217.46  Db7  2217.46  D7   2349.32  D#7  2489.02  Eb7  2489.02  E7   2637.02	\
40
	F7   2793.83  F#7  2959.96  Gb7  2959.96  G7   3135.96  G#7  3322.44  Ab7  3322.44	\
41
	A7   3520.00  A#7  3729.31  Bb7  3729.31  B7   3951.07  C8   4186.01  C#8  4434.92	\
42-
function nokia2scale(note,	octave) {
42+
43
	F#8  5919.91  Gb8  5919.91  G8   6271.93  G#8  6644.88  Ab8  6644.88  A8   7040.00	\
44
	A#8  7458.62  Bb8  7458.62  B8   7902.13", arr)
45
	for (i = 1; i <= length(arr); i += 2)
46
		scale[arr[i]] = arr[i + 1]
47
	delete arr
48
}
49
50
function nokia2scale(note,	octave)
51
{
52-
	octave += trans_octave
52+
53
	gsub(/[rR-]/, "P", note)
54
	match(note, /[a-gA-GpP#].*/)
55
	note = toupper(substr(note, RSTART, RLENGTH))
56-
function nokia2length(note,	duration, dotted) {
56+
57
	if (match(note, /[0-8]$/)) {
58
		octave = substr(note, length(note), 1)
59
		note = substr(note, 1, length(note) - 1)
60
	}
61
	if (option_adjust_octave)
62
		octave += trans_octave
63
	return (note ~ /P/) ? note : note octave
64
}
65
66
function nokia2length(note,	duration, dotted)
67-
function trim(str) { gsub(/^[ \t]+/, "", str); gsub(/[ \t]+$/, "", str); return str }
67+
68
	match(note, /^(0.|)[0-9]+/)
69-
function playnote(note) {
69+
70
	if (duration == "")
71
		duration = default_duration
72-
	printf "%s ", (qwerty) ? keymap(note) : note
72+
73-
	if (quiet) return
73+
74
	if (dotted) duration /= (1.5 * dotted)
75
	return base_time / default_beat / duration
76
}
77
78
function playnote(note)
79
{
80
	note = trim(note)
81
	if (note == "") return
82
	if (!quiet)
83
		printf "%s ", option_qwerty_midi ? keymap(note) : note
84
	delay = nokia2length(note)
85
	note  = nokia2scale(note)
86-
function playRTTL(str,	arr, value, i, first) {
86+
87-
	first = 1
87+
88-
	while (match(str, /([dob])=([0-9]+)/, arr) > 0) {
88+
89-
		if (first) {
89+
90-
			first = 0
90+
91-
			print substr(str, 1, RSTART-2)	#title
91+
92
}
93
94
function trim(s) { sub(/^[ \t]+/, "", s); sub(/[ \t]+$/, "", s); return s }
95
function after(delay) { system("sleep " delay/1000) }
96
97
function playRTTL(	str, arr, value, i, title, r)
98
{
99
	str = gensub(/\(Tempo=([0-9]+)\)/, "b=\\1", 1, $0)
100
	while (match(str, /([dob])[ \t]*=[ \t]*([0-9]+)/, arr) > 0) {
101
		if (title == "")
102
			title = substr(str, 1, arr[1, "start"] - 1)
103
		if (title ~ /:$/) title = substr(title, 1, length(title) - 1)
104-
	get_octave_range(str)
104+
105
		switch (arr[1]) {
106
		case "d": default_duration = value; break
107
		case "o": default_octave = value; break
108
		case "b": default_beat = value; break
109
		}
110
		str = substr(str, arr[2, "start"] + arr[2, "length"] + 1)
111-
	for (i = 1; i <= length(arr); i++)
111+
112-
		playnote(arr[i])
112+
	print title
113-
	print "done.\n"
113+
114
115
	trans_octave = 0
116-
function test_nokia_composer(str) {
116+
117-
	return min_octave < 3 && max_octave - min_octave < 4 || str ~ /-/
117+
118
		str = gensub(/#([a-gA-G])/, "\\1#", "g", str)
119
	}
120-
function get_octave_range(str,	arr, i, o) {
120+
121
	quiet = 0
122
	for (r = 1; r <= loop; ) {
123
		split(str, arr, /[ ,]/)
124
		for (i = 1; i <= length(arr); i++)
125
			playnote(arr[i])
126-
		if (match(arr[i], /[0-9]$/))
126+
		if (r == 1) print ""
127-
			o = substr(arr[i], RSTART, 1)
127+
		r++
128-
		if (o+0 < min_octave) min_octave = o
128+
		if (r > 1 && r <= loop) {
129-
		if (o+0 > max_octave) max_octave = o
129+
			quiet = 1	#suppress output
130
			printf "\rrepeat " r-1
131
			after(nokia2length("R"))
132
		}
133-
#http://outputchannel.com/monophonic-ringtone-synthesizer/
133+
134-
function keymap(note,	key_map) {
134+
	print "\ndone."
135-
	key_map = "Cl A C#l W Dl S D#l E El D Fl F F#l T Gl G G#l YAl H A#l U Bl J Cu K C#u O Du L D#u P Eu ; Eu [ Fu ' F#u ] Gu \\"
135+
136-
	if (note ~ /[-pP]/) return ""
136+
137
# http://nokia.nigelcoldwell.co.uk
138
function test_nokia_composer(str,	arr, i, n, o)
139
{
140
	# get octaves range (global for keymap)
141
	min_octave = 10; max_octave = -1
142
	split(str, arr, /[ ,]/)
143-
	if (match(key_map, note))
143+
144-
		return tolower(substr(key_map, RSTART+RLENGTH+1, 1))
144+
145
		if (arr[i] ~ /[-pP]/) continue
146
		if (match(arr[i], /[0-4]$/))
147
			o = substr(arr[i], RSTART, 1)+0
148-
#http://www.phoneringsong.com/nokia_composer_tones/
148+
		if (o < min_octave) min_octave = o
149
		if (o > max_octave) max_octave = o
150-
	result, arr, i, pitch, score, duration, octave, dot)
150+
151
	return str ~ /-/ || min_octave < 3 && max_octave - min_octave < 4
152-
	if (match(str, /( [0-9#*] )|(P&H)/)) {
152+
153-
		result = substr(str, 1, RSTART-1) ":"
153+
154-
		str = substr(str, RSTART)
154+
# http://outputchannel.com/monophonic-ringtone-synthesizer/
155
function keymap(note,	str)
156-
	if (match(str, /Tempo = ([0-9]+)/, arr)) {
156+
157-
		default_beat = arr[1]
157+
	str = "Cl A C#l W Dl S D#l E El D Fl F F#l T Gl G G#l Y " \
158-
		str = substr(str, arr[1, "start"] + arr[1, "length"] + 1)
158+
		"Al H A#l U Bl J Cu K C#u O Du L D#u P Eu ; Eu [ Fu ' F#u ] Gu \\"
159
	if (note ~ /[-pP]/) return "."
160-
	result = result "b=" default_beat
160+
161
	match(note, /[a-gA-GpP#].*/)
162-
	if (sony_ericsson) {
162+
163-
		gsub("0", "@", str)
163+
164-
		gsub("*", "0", str)
164+
165-
		gsub("@", "*", str)
165+
166
	if (match(str, note))
167
		return substr(str, RSTART+RLENGTH+1, 1)
168
	return "?" note "?"
169
}
170
171
# http://www.phoneringsong.com/nokia_composer_tones/
172
function keypress2composer(str,
173
	result, score, duration, octave, dot, pitch, arr, i, n)
174
{
175
	score = ""; duration = 4; octave = 1; dot = ""
176
	split("cdefgab", pitch, ""); pitch[0] = "-"
177
	match(str, "( [0-9#*] )|(P&H)")
178
	result = substr(str, 1, RSTART - 1)
179
	n = split(substr(str, RSTART), arr)
180-
		case /*/:
180+
	for (i = 1; i <= n; i++) {
181-
			if (sony_ericsson) octave = ++octave % 4
181+
		if (sony_ericsson) {
182-
			else octave = ++octave % 3
182+
			sub("0", "@", arr[i])
183
			sub("*", "0", arr[i])
184
			sub("@", "*", arr[i])
185-
		if (i < length(arr) && arr[i+1] !~ /[0-7]/)
185+
186-
			continue
186+
187-
		result = result " " sprintf("%s%s%s",
187+
188-
			duration dot, score, (score ~ /-/) ? "" : octave)
188+
189-
		score = ""; duration = 4; dot = ""
189+
190
			break
191
		case /#/: score = "#" score; break
192
		case /8/: duration *= 2; break
193
		case /9/: duration /= 2; break
194-
/^#/ { print; next }
194+
		case /[*]/:
195
			if (sony_ericsson)
196-
NF > 0 {
196+
				octave = octave++ % 4 + 1
197-
	gsub(/[\r\n]/, "")
197+
			else
198-
	if (data == "" || data ~ /,$/) {
198+
				octave = octave++ % 3 + 1
199-
		data = data $0
199+
200-
		if (data ~ /,$/)
200+
201-
			next
201+
		if (i == n || arr[i + 1] ~ /[0-7]/) {
202
			result = result " " duration dot score
203-
		data = $0
203+
			if (score !~ /r/) result = result octave
204
			score = ""; duration = 4; dot = ""
205-
	if (data ~ / [0-9#*] /) {
205+
206-
		if (data ~ /P&H/)
206+
207-
			sony_ericsson = 0
207+
208-
		data = keypress2composer(data)
208+
209
210-
	playRTTL(data)
210+
/^#/ || !NF { print; next }
211
/,$/ { buf = buf $0 " " }
212
213
{
214
215
#if (FNR == 1 && is_imelody()) {
216
# read whole data
217
# play
218
# nextfile
219
#}
220
221
	if (buf) $0 = buf $0 " "
222
	if (/ [0-9#*] /)
223
		$0 = keypress2composer($0)
224
	if (/[ドレミファソラシ]/)
225
		$0 = chakumero_conv($0)
226
	playRTTL($0)
227
	if (buf) buf = ""
228
}
229
230
# http://www.pluto.dti.ne.jp/~imasa/melody.html
231
# "テンポ=6(126)1:ドH1 2:シ1 3:ドH1 4:シ1 5:ドH1 6:-3 7:ドH1 8:シ1 9:ドH1 10:シ1 11:ドH1 12:-3 13:ドH1 14:シ1 15:ドH1 16:シ1 17:ドH1 18:-1 19:ミH1 20:-1 21:ソ6 22:ラ1 23:ソ1 24:ラ1 25:ソ1 26:ラ1 27:-3 28:ラ1 29:ソ1 30:ラ1 31:ソ1 32:ラ1 33:-3 34:ラ1 35:ソ1 36:ラ1 37:ソ1 38:ラ1 39:-1 40:ドH1 41:-1 42:ミ6 43:レ1 44:-1 45:レ1 46:ミ1 47:ファ1 48:-3 49:ファ1 50:-1 51:ファ1 52:ソ1 53:ラ1 54:-3 55:ソ1 56:-1 57:ソ1 58:ラ1 59:シ1 60:-1 61:ドH1 62:-1 63:レH6"
232
# "テンポ=7(138)1:ド1 2:ドH1 3:シ1 4:ドH1 5:ミH1 6:ドH1 7:シ1 8:ドH1 9:ド1 10:ドH1 11:ラ#1 12:ドH1 13:ミH1 14:ドH1 15:ラ#1 16:ドH1 17:ド1 18:ドH1 19:ラ1 20:ドH1 21:ミH1 22:ドH1 23:ラ1 24:ドH1 25:ド1 26:ドH1 27:ソ#1 28:ドH1 29:ミH1 30:ドH1 31:ソ#1 32:ドH1"
233
# "テンポ=6(126)1:ソL1 2:-1 3:ド1 4:ミ1 5:ソ1 6:ラ1 7:ソ1 8:ミ1 9:ファ1 10:-1 11:ファ1 12:-1 13:レ4 14:ソL1 15:-1 16:シL1 17:レ1 18:ファ1 19:ラ1 20:ソ1 21:ファ1 22:ミ1 23:-1 24:レ1 25:-1 26:ソ4 27:ソL1 28:-1 29:ド1 30:ミ1 31:ソ1 32:ラ1 33:ソ1 34:ミ1 35:ファ1 36:-1 37:ファ1 38:-1 39:レ4 40:シL1 41:レ1 42:ファ1 43:ラ1 44:ソ1 45:-1 46:シL1 47:-1 48:ド1 49:-1 50:ド1 51:-1 52:ド1 53:-3"
234
235
# http://www.geocities.co.jp/HeartLand-Namiki/8944/onpu.html
236
# "テンポ4(108)レ5/ファ#1/ソ4/-1/レ3/ミ3/レ2/ミ2/シL1/シL5/-4/-1/ド2/シL2/ラL1/シL2/ラL1/ソL2/ソL3/-1/ソL2/ファ#L2/ソL2/ミ4/レ2/ミ1/レ2/-1/レ5/ファ#1/ソ4/-1/レ3/ミ3/ファ#2/ソ2/レ1/レ5/-4/-1/ド2/シL2/ラL1/シL2/ラL1/ソL2/ソL3/-1/ソL2/レ2/ミ2/レ5/-4/-2/ミ2/ミ2/レ1/ミ3/シL1/シL2/-2/-1/ラL1/シL1/ド1/ラL2/シL1/ド1/シL2/ラL1/ソL2/-4/ソL2/ラL2/シL2/ラL4/シL2/ド2/シL4/ソL2/ソL6/-4"
237
# "テンポ3(96)レ2/ミ2/ラ↓2/ラ↓5/休2/ミ2/レ2/ミ2/ソ↓2/ソ↓5/休4/ラ↓2/シ↓2/ド2/ミ5/休2/ミ2/レ2/ミ5/レ1/ミ5/休2/レ2/ミ2/ラ↓2/ラ↓5/ミ2/ミ2/レ2/ミ2/ソ↓2/ソ↓5/ミ2/休2/ラ↓2/シ↓2/ド2/ミ4/ミ4/ミ2/レ5/ミ1/レ1/ミ5/休2/ミ2/レ2/ド2/ラ↓4/ラ↓4/ラ↓2/レ2/休2/レ2/レ4/レ2/シ↓2/シ↓1/シ↓1/ラ↓7/休4"
238
# "テンポ7(138)レ#2/レ2/レ#2/レ2/レ#4/レ2/レ#4/レ2/レ#2/レ2/レ#4/休2/ラ#↓2/ラ#↓4/レ#2/レ#5/ソ2/ソ5/ラ#2/ラ#4/ソ4/レ#7/休4/ド2/ラ#↓2/ド4/レ4/ラ#↓4/ド4/レ4/レ#4/ド4/レ4/レ#4/ファ6/休2/レ#2/レ2/レ#2/レ2/レ#4/レ2/レ#4/レ2/レ#2/レ2/レ#4/休2/ラ#↓2/ラ#↓4/レ#2/レ#5/ソ2/ソ5/ラ#2/ラ#4/ソ4/レ#7/休4/ド2/ラ#↓2/ド4/レ4/ラ#↓4/ド4/レ2/レ#0/休4/休4/休4"
239
240
# http://hasu.jp/cmelo/index.html
241
# "テンポ144 ラ2・ シ4 ラ8 ラ4 シ8 ド△4 ド△8 ド△4 レ△8 ミ△4・ ●4・ ラ4 ラ8 ラ4 ソ8 ソ4 ソ8 ラ4 ソ8 ミ4 ソ2・ ●2 ラ4 ラ8 ラ4 ラ8 シ4 シ8 ラ4 シ8 ド△4 ド△8 ド△4 レ△8 ミ△4・ ●4・ ラ4 ラ8 ラ4 ラ8 ソ4 ソ8 ラ4 シ8 ド△全 ●2"
242
# "テンポ144 ファ2・ ソ4 ファ8 ファ4 ファ8 ミ4 ミ8 ミ4 ファ8 ソ4・ ●4・ ファ4 ファ8 ファ4 ファ8 ソ4 ソ8 ソ4 ファ8 ファ4 ミ2・ ●2 ファ4 ファ8 ファ4 ファ8 ソ4 ソ8 ファ4 ファ8 ミ4 ミ8 ミ4 ファ8 ソ4・ ●4・ ファ4 ファ8 ファ4 ファ8 ソ4 ソ8 ソ4 ソ8 ソ全 ●2"
243
# "テンポ144 ファ▽2・ ソ▽2・ ラ▽4・ シ▽4・ ド4・ ソ4・ ファ2・ ソ▽2・ ド2・ ラ4・ ソ4・ ファ2・ ソ▽2・ ラ▽4・ シ▽4・ ド4・ ソ4 ファ#8 ファ2・ ソ▽2・ ド全 ド8 シ▽4 ラ▽#8"
244
245
function chakumero_conv(str,
246
	arr, i, j,note, octave, beat, tr_s, tr_d, score, duration, tie_s)
247
{	gsub("\"", "", str)
248
	octave = 4; beat = 63
249
	if (match(str, /[0-9]{2,3}/))
250
		beat = substr(str, RSTART, RLENGTH)
251
	str = substr(str, RSTART+RLENGTH+1)
252
253
	split("ド|c|レ|d|ミ|e|ファ|f|ソ|g|ラ|a|シ|b|#|#|-|p|休|p|●|p|・|.", tr_s, "|")
254
	split("9|12|8|6|7|2.|6|2|5|4.|4|4|3|8.|2|8|1|16|0|1|16|16|8|8|4|4|2|2|全|1", tr_d, "|")
255
256
	split(str, arr, "[  /]")
257
	for (i = 1; i <= length(arr); i++) {
258
		if (match(arr[i], /:/))
259
			arr[i] = substr(arr[i], RSTART+1)
260
		for (j = 1; j <= length(tr_s); j += 2) 
261
			sub(tr_s[j], tr_s[j+1], arr[i])
262
		for (j = 1; j <= length(tr_d); j += 2)
263
			if (sub(tr_d[j], tr_d[j+1], arr[i]))
264
				break
265
		if (match(arr[i], /[.0-9]+$/)) {
266
			score = substr(arr[i], 1, RSTART-1)
267
			duration = substr(arr[i], RSTART)
268
		}
269
		sub("\\^", tie_s, score); tie_s = score
270
		if (score ~ /[HL↑↓△▽]/) {
271
			score = gensub(/([△▽])#/, "#\\1", 1, score)
272
			sub(/[H↑△]/, octave+1, score)
273
			sub(/[L↓▽]/, octave-1, score)
274
		}
275
		note = duration score
276
		str = (i == 1) ? note : str "," note
277
	}
278
	return sprintf("o=%d,b=%d:%s", octave, beat, str)
279
}