Advertisement
Guest User

nokia2beeps.awk v3

a guest
Oct 9th, 2017
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.     default_duration = 4
  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.     Db8  4434.92  D8   4698.64  D#8  4978.03  Eb8  4978.03  E8   5274.04  F8   5587.65  \
  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.     gsub("\\.", "", note)
  53.     gsub(/[rR-]/, "P", note)
  54.     match(note, /[a-gA-GpP#].*/)
  55.     note = toupper(substr(note, RSTART, RLENGTH))
  56.     octave = default_octave
  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. {
  68.     match(note, /^(0.|)[0-9]+/)
  69.     duration = substr(note, RSTART, RLENGTH)
  70.     if (duration == "")
  71.         duration = default_duration
  72.     note = substr(note, RSTART+RLENGTH)
  73.     dotted = gsub("\\.", "", note)
  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.     if (note ~ /P/) {
  87.         after(delay)
  88.     } else {
  89.         if (system("beep -f " scale[note] " -l " delay " -D 0 >/dev/null"))
  90.             printf "\nError: (note,scale[note],delay)=(%s,%s,%s)\n", note, scale[note], delay
  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.         value = arr[2]
  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.     }
  112.     print title
  113.     print "beat: " default_beat
  114.  
  115.     trans_octave = 0
  116.     if (test_nokia_composer(str)) {
  117.         trans_octave = 3
  118.         str = gensub(/#([a-gA-G])/, "\\1#", "g", str)
  119.     }
  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 (r == 1) print ""
  127.         r++
  128.         if (r > 1 && r <= loop) {
  129.             quiet = 1   #suppress output
  130.             printf "\rrepeat " r-1
  131.             after(nokia2length("R"))
  132.         }
  133.     }
  134.     print "\ndone."
  135. }
  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.     for (i = 1; i <= length(arr); i++) {
  144.         o = default_octave
  145.         if (arr[i] ~ /[-pP]/) continue
  146.         if (match(arr[i], /[0-4]$/))
  147.             o = substr(arr[i], RSTART, 1)+0
  148.         if (o < min_octave) min_octave = o
  149.         if (o > max_octave) max_octave = o
  150.     }
  151.     return str ~ /-/ || min_octave < 3 && max_octave - min_octave < 4
  152. }
  153.  
  154. # http://outputchannel.com/monophonic-ringtone-synthesizer/
  155. function keymap(note,   str)
  156. {
  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.         "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.     gsub("\\.", "", note)
  161.     match(note, /[a-gA-GpP#].*/)
  162.     note = toupper(substr(note, RSTART, RLENGTH))
  163.     if (note !~ /[0-8]$/) note = note default_octave
  164.     sub(min_octave, "l", note)
  165.     sub(min_octave+1, "u", note)
  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.     for (i = 1; i <= n; i++) {
  181.         if (sony_ericsson) {
  182.             sub("0", "@", arr[i])
  183.             sub("*", "0", arr[i])
  184.             sub("@", "*", arr[i])
  185.         }
  186.         switch(arr[i]) {
  187.         case /P&H/: dot = "."
  188.         case /[0-7]/:
  189.             score = pitch[substr(arr[i], length(arr[i]), 1)]
  190.             break
  191.         case /#/: score = "#" score; break
  192.         case /8/: duration *= 2; break
  193.         case /9/: duration /= 2; break
  194.         case /[*]/:
  195.             if (sony_ericsson)
  196.                 octave = octave++ % 4 + 1
  197.             else
  198.                 octave = octave++ % 3 + 1
  199.             break
  200.         }
  201.         if (i == n || arr[i + 1] ~ /[0-7]/) {
  202.             result = result " " duration dot score
  203.             if (score !~ /r/) result = result octave
  204.             score = ""; duration = 4; dot = ""
  205.         }
  206.     }
  207.     return result
  208. }
  209.  
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement