• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ

よく使われているワード(クリックで追加)

javaandroidc++linuxc#objective-ccocoa誰得qtrubybathyscaphegamephpguicwindows翻訳pythonomegattwitterframeworkbtronarduinovb.net計画中(planning stage)directxpreviewertestゲームエンジンdom

TiMidity++ 改造版 (Windows 専用)


コミットメタ情報

リビジョン5d36000e20202f57932270704c6853013778bbd8 (tree)
日時2016-06-04 18:31:48
作者TAMUKI Shoichi <tamuki@line...>
コミッターTAMUKI Shoichi

ログメッセージ

Improve the specification of segment play option

In addition to [<minutes>:]<seconds>[.<milliseconds>] specification,
<measure>[.<beat>] specification is also now available.
For example: -G11.4-16m

Signed-off-by: TAMUKI Shoichi <tamuki@linet.gr.jp>

変更サマリ

差分

--- a/doc/C/timidity.1
+++ b/doc/C/timidity.1
@@ -452,19 +452,24 @@ In the current version of \fBTiMidity++\fP this option is a toggle.
452452 Toggles fast envelopes. This option makes \fBTiMidity++\fP faster but
453453 the release time of the notes are shortened.
454454 .TP
455-.BI "\-G " begin1-end1[,begin2-end2,...]
455+.BI "\-G " begin1-end1[,begin2-end2,...](m)
456456 .br
457457 .ns
458458 .TP
459-.BI \-\-segment= begin1-end1[,begin2-end2,...]
459+.BI \-\-segment= begin1-end1[,begin2-end2,...](m)
460460 Play just sub-segment(s) specified by comma separated time segments.
461461 .br
462462 Each time segment defined by dash separated time values of:
463-\fIbegin\fP-\fIend\fP - defaulted to 0-infinity.
463+\fIbegin\fP-\fIend\fP - defaulted to \fB0-infinity\fP.
464464 Playing from \fIbegin\fP to \fIend\fP.
465465 .sp
466466 Time format: \fI[<minutes>:]<seconds>[.<milliseconds>]\fP
467467 .sp
468+To put `m' character along with the option treats it as measure and
469+beat instead of seconds.
470+.sp
471+Time format: \fI<measure>[.<beat>]\fP (measure and beat are one-origin)
472+.sp
468473 For example:
469474 .RS
470475 .TP
@@ -474,6 +479,10 @@ Skip 12 seconds and stop at 1 minute and half a second.
474479 .B \-G-5,2:00-
475480 Play the initial 5 seconds, then skip to 2 minutes from start and play
476481 till end.
482+.TP
483+.B \-G11.4-20m -G4:00-
484+Play from the 4th beat in the 11th measure to the 20th measure, then
485+skip to 4 minutes from start and play till end.
477486 .RE
478487 .TP
479488 .BI "\-g " sec ", \-\-spectrogram=" sec
--- a/doc/ja_JP.eucJP/timidity.1
+++ b/doc/ja_JP.eucJP/timidity.1
@@ -468,19 +468,24 @@ C
468468 ープの変化時間が半分になり高速に動作します。ただし,音の立ち上がりとリ
469469 リース時間が短くなってしまいます。
470470 .TP
471-.BI "\-G " begin1-end1[,begin2-end2,...]
471+.BI "\-G " begin1-end1[,begin2-end2,...](m)
472472 .br
473473 .ns
474474 .TP
475-.BI \-\-segment= begin1-end1[,begin2-end2,...]
475+.BI \-\-segment= begin1-end1[,begin2-end2,...](m)
476476 カンマで区切った時間セグメントを指定して,複数の区間を演奏します。
477477 .br
478478 それぞれの時間セグメントは,\fIbegin\fP-\fIend\fP のように,ダッシュで
479-区切った時間で表します。デフォルトでは,0-infinity です。
479+区切った時間で表します。デフォルトでは,\fB0-infinity\fP です。
480480 \fIbegin\fP から \fIend\fP までを演奏します。
481481 .sp
482482 時間フォーマット: \fI[<分>:]<秒>[.<ミリ秒>]\fP
483483 .sp
484+オプションに `m' の文字を付加することにより,秒の代わりに小節および拍と
485+して扱います。
486+.sp
487+Time format: \fI<小節>[.<拍>]\fP (小節,拍は 1 から始まる)
488+.sp
484489 例:
485490 .RS
486491 .TP
@@ -490,6 +495,10 @@ C
490495 .B \-G-5,2:00-
491496 最初の 5 秒間を演奏したのち,開始から 2 分スキップして最後まで演奏しま
492497 す。
498+.TP
499+.B \-G11.4-20m -G4:00-
500+第 11 小節 第 4 拍から第 20 小節を演奏したのち,開始から 4 分スキップし
501+て最後まで演奏します。
493502 .RE
494503 .TP
495504 .BI "\-g " sec ", \-\-spectrogram=" sec
--- a/timidity/readmidi.c
+++ b/timidity/readmidi.c
@@ -101,7 +101,7 @@ static char **string_event_table = NULL;
101101 static int string_event_table_size = 0;
102102 int default_channel_program[256];
103103 static MidiEvent timesig[256];
104-MS_Segment *ms_segments = NULL;
104+TimeSegment *time_segments = NULL;
105105
106106 void init_delay_status_gs(void);
107107 void init_chorus_status_gs(void);
@@ -4601,40 +4601,91 @@ static void insert_note_steps(void)
46014601 }
46024602 }
46034603
4604-static int32 compute_smf_at_time(const int32);
4604+static int32 compute_smf_at_time(const int32, int32 *);
4605+static int32 compute_smf_at_time2(const Measure, int32 *);
46054606
46064607 static void insert_cuepoints(void)
46074608 {
4608- MS_Segment *sp;
4609- int32 at, t;
4609+ TimeSegment *sp;
4610+ int32 at, st, t;
46104611 uint8 a0, b0, a1, b1;
46114612
4612- for (sp = ms_segments; sp != NULL; sp = sp->next) {
4613- if (sp->prev == NULL && sp->begin != 0) {
4614- at = compute_smf_at_time(0);
4615- t = sp->begin * play_mode->rate;
4616- a0 = t >> 24, b0 = t >> 16, a1 = t >> 8, b1 = t;
4617- MIDIEVENT(at, ME_NOTEON, 0, 0, 0);
4618- MIDIEVENT(at, ME_CUEPOINT, 0, a0, b0);
4619- MIDIEVENT(at, ME_CUEPOINT, 1, a1, b1);
4613+ for (sp = time_segments; sp != NULL; sp = sp->next) {
4614+ if (sp->type == 0) {
4615+ if (sp->prev == NULL && sp->begin.s != 0) {
4616+ t = sp->begin.s * play_mode->rate;
4617+ a0 = t >> 24, b0 = t >> 16, a1 = t >> 8, b1 = t;
4618+ MIDIEVENT(0, ME_NOTEON, 0, 0, 0);
4619+ MIDIEVENT(0, ME_CUEPOINT, 0, a0, b0);
4620+ MIDIEVENT(0, ME_CUEPOINT, 1, a1, b1);
4621+ }
4622+ if (sp->next != NULL) {
4623+ at = compute_smf_at_time(sp->end.s * play_mode->rate, &st);
4624+ if (sp->next->type == 0)
4625+ t = sp->next->begin.s * play_mode->rate - st;
4626+ else
4627+ compute_smf_at_time2(sp->next->begin.m, &t), t -= st;
4628+ a0 = t >> 24, b0 = t >> 16, a1 = t >> 8, b1 = t;
4629+ MIDIEVENT(at, ME_CUEPOINT, 0, a0, b0);
4630+ MIDIEVENT(at, ME_CUEPOINT, 1, a1, b1);
4631+ } else if (sp->end.s != -1) {
4632+ at = compute_smf_at_time(sp->end.s * play_mode->rate, &st);
4633+ t = 0x7fffffff; /* stopper */
4634+ a0 = t >> 24, b0 = t >> 16, a1 = t >> 8, b1 = t;
4635+ MIDIEVENT(at, ME_CUEPOINT, 0, a0, b0);
4636+ MIDIEVENT(at, ME_CUEPOINT, 1, a1, b1);
4637+ }
4638+ } else {
4639+ if (sp->prev == NULL
4640+ && (sp->begin.m.meas != 1 || sp->begin.m.beat != 1)) {
4641+ compute_smf_at_time2(sp->begin.m, &t);
4642+ a0 = t >> 24, b0 = t >> 16, a1 = t >> 8, b1 = t;
4643+ MIDIEVENT(0, ME_NOTEON, 0, 0, 0);
4644+ MIDIEVENT(0, ME_CUEPOINT, 0, a0, b0);
4645+ MIDIEVENT(0, ME_CUEPOINT, 1, a1, b1);
4646+ }
4647+ if (sp->next != NULL) {
4648+ at = compute_smf_at_time2(sp->end.m, &st);
4649+ if (sp->next->type == 0)
4650+ t = sp->next->begin.s * play_mode->rate - st;
4651+ else
4652+ compute_smf_at_time2(sp->next->begin.m, &t), t -= st;
4653+ a0 = t >> 24, b0 = t >> 16, a1 = t >> 8, b1 = t;
4654+ MIDIEVENT(at, ME_CUEPOINT, 0, a0, b0);
4655+ MIDIEVENT(at, ME_CUEPOINT, 1, a1, b1);
4656+ } else if (sp->end.m.meas != -1 || sp->end.m.beat != -1) {
4657+ at = compute_smf_at_time2(sp->end.m, &st);
4658+ t = 0x7fffffff; /* stopper */
4659+ a0 = t >> 24, b0 = t >> 16, a1 = t >> 8, b1 = t;
4660+ MIDIEVENT(at, ME_CUEPOINT, 0, a0, b0);
4661+ MIDIEVENT(at, ME_CUEPOINT, 1, a1, b1);
4662+ }
46204663 }
4621- if (sp->next != NULL) {
4622- at = compute_smf_at_time(sp->end * play_mode->rate);
4623- t = (sp->next->begin - sp->end) * play_mode->rate;
4624- a0 = t >> 24, b0 = t >> 16, a1 = t >> 8, b1 = t;
4625- MIDIEVENT(at, ME_CUEPOINT, 0, a0, b0);
4626- MIDIEVENT(at, ME_CUEPOINT, 1, a1, b1);
4627- } else if (sp->end != -1) {
4628- at = compute_smf_at_time(sp->end * play_mode->rate);
4629- t = 0x7fffffff; /* stopper */
4630- a0 = t >> 24, b0 = t >> 16, a1 = t >> 8, b1 = t;
4631- MIDIEVENT(at, ME_CUEPOINT, 0, a0, b0);
4632- MIDIEVENT(at, ME_CUEPOINT, 1, a1, b1);
4664+ }
4665+}
4666+
4667+static int32 compute_smf_at_time(const int32 sample, int32 *sample_adj)
4668+{
4669+ MidiEventList *e;
4670+ int32 st = 0, tempo = 500000, prev_time = 0;
4671+ int i;
4672+
4673+ for (i = 0, e = evlist; i < event_count; i++, e = e->next) {
4674+ st += (double) tempo * play_mode->rate / 1000000
4675+ / current_file_info->divisions
4676+ * (e->event.time - prev_time) + 0.5;
4677+ if (st >= sample && e->event.type == ME_NOTE_STEP) {
4678+ *sample_adj = st;
4679+ return e->event.time;
46334680 }
4681+ if (e->event.type == ME_TEMPO)
4682+ tempo = e->event.a * 65536 + e->event.b * 256 + e->event.channel;
4683+ prev_time = e->event.time;
46344684 }
4685+ return -1;
46354686 }
46364687
4637-static int32 compute_smf_at_time(const int32 sample)
4688+static int32 compute_smf_at_time2(const Measure m, int32 *sample)
46384689 {
46394690 MidiEventList *e;
46404691 int32 st = 0, tempo = 500000, prev_time = 0;
@@ -4644,8 +4695,12 @@ static int32 compute_smf_at_time(const int32 sample)
46444695 st += (double) tempo * play_mode->rate / 1000000
46454696 / current_file_info->divisions
46464697 * (e->event.time - prev_time) + 0.5;
4647- if (st >= sample && e->event.type == ME_NOTE_STEP)
4698+ if (e->event.type == ME_NOTE_STEP
4699+ && ((e->event.a + ((e->event.b & 0x0f) << 8)) * 16
4700+ + (e->event.b >> 4)) >= m.meas * 16 + m.beat) {
4701+ *sample = st;
46484702 return e->event.time;
4703+ }
46494704 if (e->event.type == ME_TEMPO)
46504705 tempo = e->event.a * 65536 + e->event.b * 256 + e->event.channel;
46514706 prev_time = e->event.time;
@@ -4653,13 +4708,13 @@ static int32 compute_smf_at_time(const int32 sample)
46534708 return -1;
46544709 }
46554710
4656-void free_ms_segments(void)
4711+void free_time_segments(void)
46574712 {
4658- MS_Segment *sp, *next;
4713+ TimeSegment *sp, *next;
46594714
4660- for (sp = ms_segments; sp != NULL; sp = next)
4715+ for (sp = time_segments; sp != NULL; sp = next)
46614716 next = sp->next, free(sp);
4662- ms_segments = NULL;
4717+ time_segments = NULL;
46634718 }
46644719
46654720 MidiEvent *read_midi_file(struct timidity_file *tf, int32 *count, int32 *sp,
@@ -6343,7 +6398,7 @@ void remove_channel_layer(int ch)
63436398 void free_readmidi(void)
63446399 {
63456400 reuse_mblock(&mempool);
6346- free_ms_segments();
6401+ free_time_segments();
63476402 free_all_midi_file_info();
63486403 free_userdrum();
63496404 free_userinst();
--- a/timidity/readmidi.h
+++ b/timidity/readmidi.h
@@ -113,12 +113,24 @@ struct midi_file_info
113113 struct timidity_file *pcm_tf;
114114 };
115115
116-typedef struct _MS_Segment {
117- FLOAT_T begin;
118- FLOAT_T end;
119- struct _MS_Segment *prev;
120- struct _MS_Segment *next;
121-} MS_Segment;
116+typedef struct {
117+ int meas;
118+ int beat;
119+} Measure;
120+
121+typedef struct _TimeSegment {
122+ int type; /* seconds: 0, measure: 1 */
123+ union {
124+ FLOAT_T s;
125+ Measure m;
126+ } begin;
127+ union {
128+ FLOAT_T s;
129+ Measure m;
130+ } end;
131+ struct _TimeSegment *prev;
132+ struct _TimeSegment *next;
133+} TimeSegment;
122134
123135 extern int32 readmidi_set_track(int trackno, int rewindp);
124136 extern void readmidi_add_event(MidiEvent *newev);
@@ -130,7 +142,7 @@ extern int convert_midi_control_change(int chn, int type, int val,
130142 extern int unconvert_midi_control_change(MidiEvent *ev);
131143 extern char *readmidi_make_string_event(int type, char *string, MidiEvent *ev,
132144 int cnv);
133-extern void free_ms_segments(void);
145+extern void free_time_segments(void);
134146 extern MidiEvent *read_midi_file(struct timidity_file *mtf,
135147 int32 *count, int32 *sp, char *file_name);
136148 extern struct midi_file_info *get_midi_file_info(char *filename,int newp);
@@ -148,7 +160,7 @@ extern int dump_current_timesig(MidiEvent *codes, int maxlen);
148160
149161 extern ChannelBitMask quietchannels;
150162 extern struct midi_file_info *current_file_info;
151-extern MS_Segment *ms_segments;
163+extern TimeSegment *time_segments;
152164 extern int opt_trace_text_meta_event;
153165 extern int opt_default_mid;
154166 extern int opt_system_mid;
--- a/timidity/timidity.c
+++ b/timidity/timidity.c
@@ -437,8 +437,11 @@ static inline int parse_opt_e(const char *);
437437 static inline int parse_opt_F(const char *);
438438 static inline int parse_opt_f(const char *);
439439 static inline int parse_opt_G(const char *);
440-static int parse_segment(MS_Segment *, const char *);
440+static inline int parse_opt_G1(const char *);
441+static int parse_segment(TimeSegment *, const char *);
442+static int parse_segment2(TimeSegment *, const char *);
441443 static int parse_time(FLOAT_T *, const char *);
444+static int parse_time2(Measure *, const char *);
442445 static inline int parse_opt_g(const char *);
443446 static inline int parse_opt_H(const char *);
444447 __attribute__((noreturn))
@@ -3616,73 +3619,157 @@ static inline int parse_opt_f(const char *arg)
36163619
36173620 static inline int parse_opt_G(const char *arg)
36183621 {
3619- /* play just sub-segment(s) */
3620- MS_Segment *sp;
3622+ /* play just sub-segment(s) (seconds) */
3623+ TimeSegment *sp;
36213624 const char *p = arg;
3625+ int prev_end;
36223626
3623- if (ms_segments == NULL) {
3624- ms_segments = (MS_Segment *) safe_malloc(sizeof(MS_Segment));
3625- if (parse_segment(ms_segments, p)) {
3626- free_ms_segments();
3627+ if (strchr(arg, 'm'))
3628+ return parse_opt_G1(arg);
3629+ if (time_segments == NULL) {
3630+ time_segments = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3631+ time_segments->type = 0;
3632+ if (parse_segment(time_segments, p)) {
3633+ free_time_segments();
36273634 return 1;
36283635 }
3629- ms_segments->prev = ms_segments->next = NULL, sp = ms_segments;
3636+ time_segments->prev = time_segments->next = NULL, sp = time_segments;
36303637 } else {
3631- for (sp = ms_segments; sp->next != NULL; sp = sp->next)
3638+ for (sp = time_segments; sp->next != NULL; sp = sp->next)
36323639 ;
3633- sp->next = (MS_Segment *) safe_malloc(sizeof(MS_Segment));
3640+ sp->next = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3641+ sp->next->type = 0;
36343642 if (parse_segment(sp->next, p)) {
3635- free_ms_segments();
3643+ free_time_segments();
36363644 return 1;
36373645 }
36383646 sp->next->prev = sp, sp->next->next = NULL, sp = sp->next;
36393647 }
36403648 while ((p = strchr(p, ',')) != NULL) {
3641- sp->next = (MS_Segment *) safe_malloc(sizeof(MS_Segment));
3649+ sp->next = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3650+ sp->next->type = 0;
36423651 if (parse_segment(sp->next, ++p)) {
3643- free_ms_segments();
3652+ free_time_segments();
36443653 return 1;
36453654 }
36463655 sp->next->prev = sp, sp->next->next = NULL, sp = sp->next;
36473656 }
3648- for (sp = ms_segments; sp != NULL; sp = sp->next)
3649- if (sp->prev != NULL && sp->begin <= sp->prev->end) {
3657+ prev_end = -1;
3658+ for (sp = time_segments; sp != NULL; sp = sp->next) {
3659+ if (sp->type != 0)
3660+ continue;
3661+ if (sp->begin.s <= prev_end) {
36503662 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Segments must be ordered");
3651- free_ms_segments();
3663+ free_time_segments();
36523664 return 1;
3653- } else if (sp->end != -1 && sp->begin >= sp->end) {
3665+ } else if (sp->end.s != -1 && sp->begin.s >= sp->end.s) {
36543666 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Segment time must be ordered");
3655- free_ms_segments();
3667+ free_time_segments();
36563668 return 1;
36573669 }
3670+ prev_end = sp->end.s;
3671+ }
36583672 return 0;
36593673 }
36603674
3661-static int parse_segment(MS_Segment *seg, const char *p)
3675+static inline int parse_opt_G1(const char *arg)
3676+{
3677+ /* play just sub-segment(s) (measure) */
3678+ TimeSegment *sp;
3679+ const char *p = arg;
3680+ int prev_end_meas, prev_end_beat;
3681+
3682+ if (time_segments == NULL) {
3683+ time_segments = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3684+ time_segments->type = 1;
3685+ if (parse_segment2(time_segments, p)) {
3686+ free_time_segments();
3687+ return 1;
3688+ }
3689+ time_segments->prev = time_segments->next = NULL, sp = time_segments;
3690+ } else {
3691+ for (sp = time_segments; sp->next != NULL; sp = sp->next)
3692+ ;
3693+ sp->next = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3694+ sp->next->type = 1;
3695+ if (parse_segment2(sp->next, p)) {
3696+ free_time_segments();
3697+ return 1;
3698+ }
3699+ sp->next->prev = sp, sp->next->next = NULL, sp = sp->next;
3700+ }
3701+ while ((p = strchr(p, ',')) != NULL) {
3702+ sp->next = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3703+ sp->next->type = 1;
3704+ if (parse_segment2(sp->next, ++p)) {
3705+ free_time_segments();
3706+ return 1;
3707+ }
3708+ sp->next->prev = sp, sp->next->next = NULL, sp = sp->next;
3709+ }
3710+ prev_end_meas = prev_end_beat = -1;
3711+ for (sp = time_segments; sp != NULL; sp = sp->next) {
3712+ if (sp->type != 1)
3713+ continue;
3714+ if (sp->begin.m.meas * 16 + sp->begin.m.beat
3715+ <= prev_end_meas * 16 + prev_end_beat) {
3716+ ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Segments must be ordered");
3717+ free_time_segments();
3718+ return 1;
3719+ } else if (sp->end.m.meas != -1 && sp->end.m.beat != -1
3720+ && sp->begin.m.meas * 16 + sp->begin.m.beat
3721+ >= sp->end.m.meas * 16 + sp->end.m.beat) {
3722+ ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Segment time must be ordered");
3723+ free_time_segments();
3724+ return 1;
3725+ }
3726+ prev_end_meas = sp->end.m.meas, prev_end_beat = sp->end.m.beat;
3727+ }
3728+ return 0;
3729+}
3730+
3731+static int parse_segment(TimeSegment *seg, const char *p)
36623732 {
36633733 const char *q;
36643734
36653735 if (*p == '-')
3666- seg->begin = 0;
3667- else if (parse_time(&seg->begin, p))
3736+ seg->begin.s = 0;
3737+ else if (parse_time(&seg->begin.s, p))
36683738 return 1;
36693739 p = ((q = strchr(p, '-')) == NULL) ? p + strlen(p) : q + 1;
36703740 if (*p == ',' || *p == '\0')
3671- seg->end = -1;
3672- else if (parse_time(&seg->end, p))
3741+ seg->end.s = -1;
3742+ else if (parse_time(&seg->end.s, p))
3743+ return 1;
3744+ return 0;
3745+}
3746+
3747+static int parse_segment2(TimeSegment *seg, const char *p)
3748+{
3749+ const char *q;
3750+
3751+ if (*p == '-')
3752+ seg->begin.m.meas = seg->begin.m.beat = 1;
3753+ else if (parse_time2(&seg->begin.m, p))
3754+ return 1;
3755+ p = ((q = strchr(p, '-')) == NULL) ? p + strlen(p) : q + 1;
3756+ if (*p == ',' || *p == 'm')
3757+ seg->end.m.meas = seg->end.m.beat = -1;
3758+ else if (parse_time2(&seg->end.m, p))
36733759 return 1;
36743760 return 0;
36753761 }
36763762
36773763 static int parse_time(FLOAT_T *param, const char *p)
36783764 {
3679- const char *p1, *p2;
3765+ const char *p1, *p2, *p3;
36803766 int min;
36813767 FLOAT_T sec;
36823768
36833769 p1 = ((p1 = strchr(p, ':')) == NULL) ? p + strlen(p) : p1;
36843770 p2 = ((p2 = strchr(p, '-')) == NULL) ? p + strlen(p) : p2;
3685- if (p1 < p2) {
3771+ p3 = ((p3 = strchr(p, ',')) == NULL) ? p + strlen(p) : p3;
3772+ if ((p1 < p2 && p2 <= p3) || (p1 < p3 && p3 <= p2)) {
36863773 if (set_value(&min, atoi(p), 0, 59, "Segment time (min part)"))
36873774 return 1;
36883775 if (parse_val_float_t(&sec, p1 + 1, 0, 59.999,
@@ -3694,6 +3781,24 @@ static int parse_time(FLOAT_T *param, const char *p)
36943781 return 0;
36953782 }
36963783
3784+static int parse_time2(Measure *param, const char *p)
3785+{
3786+ const char *p1, *p2, *p3;
3787+
3788+ if (set_value(&param->meas, atoi(p), 0, 999, "Segment time (measure)"))
3789+ return 1;
3790+ p1 = ((p1 = strchr(p, '.')) == NULL) ? p + strlen(p) : p1;
3791+ p2 = ((p2 = strchr(p, '-')) == NULL) ? p + strlen(p) : p2;
3792+ p3 = ((p3 = strchr(p, ',')) == NULL) ? p + strlen(p) : p3;
3793+ if ((p1 < p2 && p2 <= p3) || (p1 < p3 && p3 <= p2)) {
3794+ if (set_value(&param->beat, atoi(p1 + 1), 1, 15,
3795+ "Segment time (beat)"))
3796+ return 1;
3797+ } else
3798+ param->beat = 1;
3799+ return 0;
3800+}
3801+
36973802 static inline int parse_opt_g(const char *arg)
36983803 {
36993804 #ifdef SUPPORT_SOUNDSPEC
@@ -3840,12 +3945,15 @@ static int parse_opt_h(const char *arg)
38403945 "Enable "
38413946 #endif
38423947 "fast decay mode (toggle)",
3843-" -G --segment=<begin>-<end>[,<begin2>-<end2>,...]",
3948+" -G <begin>-<end>[,<begin2>-<end2>,...](m)",
3949+" --segment=<begin>-<end>[,<begin2>-<end2>,...](m)",
38443950 " Play just sub-segment(s), comma separated segments",
3845-" Each segment is dash separated of two time values of:",
3846-" <begin>-<end> - defaulted to 0-infinity",
3847-" Playing from <begin> to <end>",
3848-" Time format: [<minutes>:]<seconds>[.<milliseconds>]",
3951+" Each segment is dash separated of two time values of:",
3952+" <begin>-<end> - defaulted to 0-infinity",
3953+" Playing from <begin> to <end>",
3954+" Time format: [<minutes>:]<seconds>[.<milliseconds>]",
3955+" 'm' stands for using measure and beat instead of secs",
3956+" Time format: <measure>[.<beat>] (one-origin)",
38493957 #ifdef SUPPORT_SOUNDSPEC
38503958 " -g sec --spectrogram=sec",
38513959 " Open Sound-Spectrogram Window",
@@ -5107,7 +5215,7 @@ static int parse_val_float_t(FLOAT_T *param,
51075215 {
51085216 FLOAT_T value;
51095217 char *errp;
5110-
5218+
51115219 value = strtod(arg, &errp);
51125220 if (arg == errp) {
51135221 /* only when nothing was parsed */