如何将转换函数应用于数据文件的索引以在每个时间间隔生成
xticlabels
?
在这里我想使用我的用户定义的
secs_to_beats_bars
函数(它返回一个格式化为sprintf
的字符串),见下文。
注意,我正在努力避免以下情况:
假设我有一个数据文件,以秒为单位索引(十进制):
# Seconds, Pitch, Duration, Velocity
0.16129032258064513, 31, 0.7157258064516129, 71
0.8870967741935483, 31, 0.3578629032258066, 75
1.2499999999999998, 31, 0.3427419354838712, 78
1.6129032258064513, 42, 0.4637096774193551, 75
2.0967741935483866, 37, 0.7056451612903228, 76
2.82258064516129, 33, 0.3427419354838712, 77
3.1854838709677415, 31, 0.3427419354838712, 78
3.548387096774193, 31, 0.46370967741935554, 74
4.032258064516128, 31, 1.0735887096774201, 71
5.120967741935483, 33, 0.34778225806451696, 62
5.483870967741934, 31, 0.32258064516129087, 50
5.806451612903225, 35, 0.48387096774193544, 87
5.96774193548387, 43, 0.3528225806451618, 63
6.330645161290321, 31, 0.7106854838709676, 58
我有一个自定义功能,可以将秒数转换为与音乐相关的时间系统(如节拍和小节):
# tempo is in beats per minute, beats and bars are indexed from one.
# eg: bar 1 beat 1 = "1:1"
secs_to_beats(secs, tempo) = int(secs * tempo / 60);
secs_to_beats_bars(secs, tempo, beatsperbar) = sprintf('%.0f:%.0f', int(secs_to_beats(secs, tempo) / beatsperbar) + 1, secs_to_beats(secs, tempo) % beatsperbar + 1);
我用它在每个节拍以固定间隔设置
xtics
,以及 mxtics
进一步将网格细分为 semiquavers:
beats_to_secs(beat, tempo) = 1.0/(tempo * 1.0/60.0) * beat;
bpm = 80;
beatinterval = beats_to_secs(1, bpm);
set xtics beatinterval; set mxtics 4; set grid x mx ls 100, ls 101;
最后使用
boxxyerror
绘制此图,使用秒数、音高和持续时间列为每一行创建矩形:
set yrange[0:127];
plot 'midi.dat' u (($1+$3)/2):(($2+0.95)/2):1:($3+$1):($2):($2+0.95) w boxxy fs solid 0.50 border lc 'black';
如您所见,
xticlabels
以秒为单位,我正在尝试使用上面的 secs_to_beats_bars
函数将这些转换为节拍/小节。
我想下面的例子可以满足您的要求:
此外:
boxxyerror
(x):(y):(+/-dx):(+/-dy)
,检查help boxxyerror
.在你的脚本中添加因素
1.0
,我假设你知道gnuplot的整数除法(例如1/2 = 0
)。
脚本:
### change x-axis scale
reset session
$Data <<EOD
# Seconds, Pitch, Duration, Velocity
0.16129032258064513, 31, 0.7157258064516129, 71
0.8870967741935483, 31, 0.3578629032258066, 75
1.2499999999999998, 31, 0.3427419354838712, 78
1.6129032258064513, 42, 0.4637096774193551, 75
2.0967741935483866, 37, 0.7056451612903228, 76
2.82258064516129, 33, 0.3427419354838712, 77
3.1854838709677415, 31, 0.3427419354838712, 78
3.548387096774193, 31, 0.46370967741935554, 74
4.032258064516128, 31, 1.0735887096774201, 71
5.120967741935483, 33, 0.34778225806451696, 62
5.483870967741934, 31, 0.32258064516129087, 50
5.806451612903225, 35, 0.48387096774193544, 87
5.96774193548387, 43, 0.3528225806451618, 63
6.330645161290321, 31, 0.7106854838709676, 58
EOD
BPM = 80 # beats per minute
BPB = 4 # beats per bar
OFF = 0.000 # offset in seconds
SecToBar(s) = s*BPM/60./BPB
BoxCenter(colS,colD) = SecToBar(column(colS) + column(colD)*0.5 + OFF) + 1
BoxWidth(colD) = SecToBar(column(colD))*0.5
set datafile separator comma
set style line 1 lw 1.5 lc "red"
set style line 2 lw 1.0 lc "grey"
set style fill solid 0.50 transparent border lc 'black'
set key noautotitle
set xlabel "bars"
set xtics 1
set mxtics BPB
set grid x,mx ls 1, ls 2
set ylabel "pitch"
set yrange[25:50]
plot $Data u (BoxCenter(1,3)):2:(BoxWidth(3)):(0.45) w boxxy lc 'blue'
### end of script
结果: