home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.ee.lbl.gov
/
2014.05.ftp.ee.lbl.gov.tar
/
ftp.ee.lbl.gov
/
bmd-1.0beta.tar.Z
/
bmd-1.0beta.tar
/
bmd-1.0beta
/
app
/
omtd
/
merge.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-21
|
8KB
|
423 lines
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Lawrence Berkeley Laboratory,
* Berkeley, CA. The name of the University may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <sys/types.h>
#include <sundev/midi.h>
#include "readline.h"
#include "event.h"
#include "setting.h"
#include "etime.h"
#include "track.h"
/*
* Merge last track recorded into a track.
*/
void
merge_command(trkp)
struct track *trkp;
{
struct event *raw, **masterp, *p;
struct event *pending;
u_long lasttime;
int n = 0, new_track = 0;
pending = 0;
masterp = &master_list;
for (raw = raw_list; raw != 0; raw = raw->next)
{
if (evt_noteoff_p(raw))
{
p = pq_remove_bynote(&pending, raw->m.mm_data[1]);
if (p != 0)
p->duration = unwarp_time(s.tempo,
raw->m.mm_time)
- p->m.mm_time;
continue;
}
++n;
p = ealloc();
p->trk = trkp;
p->m = raw->m;
p->m.mm_time = unwarp_time(s.tempo, raw->m.mm_time);
if (evt_noteon_p(raw))
pq_insert(&pending, p);
/*
* Insert event in master list.
*/
while (*masterp && (*masterp)->m.mm_time <= p->m.mm_time)
masterp = &(*masterp)->next;
p->next = *masterp;
*masterp = p;
}
if (pending)
{
lasttime = p->m.mm_time;
for (; pending != 0; pending = pending->pqnext)
pending->duration = lasttime - pending->m.mm_time;
}
printf("Merged %d events\n", n);
efreel(raw_list);
raw_list = 0;
}
void
channel_command(trkp, channel)
struct track *trkp;
int channel;
{
trkp->channel = (channel - 1) & 0xf;
}
void
clear_command(trk, start, end)
struct track *trk;
int start, end;
{
struct event **pp;
pp = &master_list;
while (*pp != 0) {
if ((*pp)->trk == trk &&
(*pp)->m.mm_time >= start &&
(*pp)->m.mm_time < end) {
struct event *tmp = *pp;
*pp = (*pp)->next;
efree(tmp);
} else
pp = &(*pp)->next;
}
}
void
move_command(amt, start)
int amt, start;
{
struct event *p;
for (p = master_list; p != 0; p = p->next) {
if (p->m.mm_time >= start)
p->m.mm_time += amt;
}
}
void
mute_command(trk, val)
struct track *trk;
int val;
{
if (trk == 0)
return;
trk->mute = val;
}
void
unmute_command(tp)
struct token *tp;
{
struct track *trk;
struct event **pp;
int mute = 0;
if (tp == 0)
{
for (trk = trklist; trk != 0; trk = trk->next)
trk->mute = mute;
return;
}
else if (tp->t_id != TK_IDENT)
{
error ("unmute track_name");
return;
}
if ((trk = find_track(tp->t_str)) != 0)
trk->mute = mute;
}
struct event *
copyout_track(trk, start, end)
struct track *trk;
u_long start, end;
{
struct event *head, **pp = &head, *p;
for (p = master_list; p != 0; p = p->next)
{
if (p->trk == trk &&
p->m.mm_time >= start && p->m.mm_time < end)
{
*pp = ealloc();
**pp = *p;
pp = &(*pp)->next;
}
}
*pp = 0;
return head;
}
struct event *
extract_track(trk, start, end)
struct track *trk;
u_long start, end;
{
struct event *head, **pp = &head, *p, **op;
op = &master_list;
while (*op != 0)
{
if ((*op)->trk == trk &&
(*op)->m.mm_time >= start && (*op)->m.mm_time < end)
{
*pp = *op;
pp = &(*pp)->next;
*op = (*op)->next;
}
else
op = &(*op)->next;
}
*pp = 0;
return head;
}
void
insert_list(elist)
struct event *elist;
{
struct event **pp, *p;
pp = &master_list;
while (elist != 0)
{
while (*pp && (*pp)->m.mm_time <= elist->m.mm_time)
pp = &(*pp)->next;
p = elist;
elist = elist->next;
p->next = *pp;
*pp = p;
}
}
void
copy_command(strk, start, end, dtrk, dstart, repeat)
struct track *strk, *dtrk;
u_long start = 0, end = ~0, dstart;
{
u_long delta;
struct event *elist, *p;
if (repeat > 1 && end == ~0) {
printf("must give length if repeat > 0\n");
return;
}
if (start > end) {
printf("start time must be less than end time\n");
return;
}
delta = dstart - start;
while (--repeat >= 0) {
elist = copyout_track(strk, start, end);
for (p = elist; p != 0; p = p->next) {
p->trk = dtrk;
p->m.mm_time += delta;
}
insert_list(elist);
delta += end - start;
}
}
void
quantize_command(trk, n, d)
struct track *trk;
int n, d;
{
struct event *p;
int t, r;
if (d == 0) {
printf("error: division by zero\n");
return;
}
r = s.ticks_per_beat * n * 4;
r /= d;
for (p = master_list; p != 0; p = p->next) {
if (p->trk == trk) {
t = p->m.mm_time;
t += r / 2;
t -= t % r;
p->m.mm_time = t;
}
}
}
void
insert_command(tp)
struct token *tp;
{
struct track *trk;
struct event *p, *newlist;
u_long at = 0, amt = 0;
if (tp == 0 || tp->t_id != TK_IDENT)
goto bad;
trk = find_track(tp->t_str);
if (trk == 0)
return;
tp = tp->next;
if (tp == 0 || tp->t_id != ':')
goto bad;
tp = tp->next;
if (tp == 0)
goto bad;
tp = parse_time(tp, &at);
if (tp == 0)
goto bad;
tp = parse_time(tp, &amt);
if (amt == 0)
return;
newlist = extract_track(trk, at, (u_long)~0);
for (p = newlist; p != 0; p = p->next)
p->m.mm_time += amt;
insert_list(newlist);
return;
bad:
printf("error: insert trk:time amt\n");
}
void
volume_command(tp)
struct token *tp;
{
struct track *trk;
struct event *p, *newlist;
int volume;
u_long start = 0, end = ~0;
if (tp == 0 || tp->t_id != TK_INT)
goto bad;
volume = tp->t_int;
tp = tp->next;
if (tp == 0 || tp->t_id != TK_IDENT)
goto bad;
trk = find_track(tp->t_str);
if (trk == 0)
return;
tp = tp->next;
if (tp && tp->t_id == ':')
{
tp = tp->next;
tp = parse_time(tp, &start);
if (tp && tp->t_id == ',')
{
tp = tp->next;
tp = parse_time(tp, &end);
}
}
for (p = master_list; p != 0; p = p->next)
if (p->trk == trk && (p->m.mm_cmd & 0xf0) == 0x90 &&
p->m.mm_time >= start && p->m.mm_time < end)
p->m.mm_data[2] = volume;
return;
bad:
printf("error: volume amt trk:time\n");
}
#define BAR_TO_TIME(bar, beat) (((bar) * s.beats_per_bar + (beat)) * \
s.ticks_per_beat)
void
transpose_command(tp)
struct token *tp;
{
int all_flag = 1, /* transpose all tracks? */
trans_num, /* # of notes by which to tranpose */
sign = 1;
struct track *trk; /* track */
struct event *p, *curr;
u_long st = 0, /* start time */
et = ~0; /* end time */
if (tp && tp->t_id == TK_IDENT)
{
trk = find_track(tp->t_str);
all_flag = 0;
}
if (tp == 0)
goto bad;
tp = tp->next;
if (tp && tp->t_id == ':')
tp = parse_window(tp->next, &st, &et);
if (tp == 0)
goto bad;
if (tp->t_id == '-')
{
sign = -1;
tp = tp->next;
}
if (tp == 0 || tp->t_id != TK_INT)
goto bad;
trans_num = tp->t_int * sign;
tp = tp->next;
if (tp != 0)
goto bad;
for (p = master_list; p != 0; p = p->next)
{
if ((all_flag || p->trk == trk) &&
p->m.mm_time >= st &&
p->m.mm_time < et)
{
if (p->m.mm_data[1] + trans_num > 127)
{
printf("Warning! Tranposition out of range.");
printf("\nUndoing transposition.\n");
for (curr = master_list; curr != p;
curr = curr->next)
if ((all_flag || curr->trk == trk) &&
curr->m.mm_time >= st &&
curr->m.mm_time < et)
{
curr->m.mm_data[1] -=
trans_num;
}
break;
}
p->m.mm_data[1] += trans_num;
}
}
return;
bad:
error("trans [track] [:[start_time][, end_time]] #_of_half_tones");
}