将自定义 xtic 标签设置为 xtic 值的函数

问题描述 投票:0回答:1

问题

如何将转换函数应用于数据文件的索引以在每个时间间隔生成

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
函数将这些转换为节拍/小节。

plot gnuplot
1个回答
0
投票

我想下面的例子可以满足您的要求:

  • 没有手动抽动标签
  • 原始数据不变
  • x 轴以条而不是秒为单位

此外:

  • 如果第一个音符不在节拍上,您可以设置一个偏移量。
  • 我使用了绘图样式的4列语法
    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

结果:

© www.soinside.com 2019 - 2024. All rights reserved.