+2000-05-08 Masanao Izumo <mo@goice.co.jp>
+
+ * Version 2.9.3 released.
+
+2000-05-08 Masanao Izumo <mo@goice.co.jp>
+
+ * interface/{Makefile.am,Makefile.in}: Changed target dependancy for
+ tclIndex not to change tclIndex unless the tcl-sources are changed.
+
+2000-04-20 Eric A. Welsh <ewelsh@gpc.wustl.edu>
+
+ * timidity/{resample.c,recache.c,playmidi.c}: Fix the previous patch.
+ - Drum & Sample pan fix.
+ - Remove pre_resampling().
+ - And else...
+
+2000-04-15 Eric A. Welsh <ewelsh@gpc.wustl.edu>
+
+ * timidity/playmidi.c: Fixed voice reduction control.
+ * timidity/{instrum.c,sndfont.c}: Removed the pre_resampling() calls
+ in order to enable drum pitch bends.
+ * timidity/readmidi.c: Remove duplicated code.
+ * timidity/playmidi.c: Enable to get chorus level in drum channel.
+
+2000-04-14 Eric A. Welsh <ewelsh@gpc.wustl.edu>
+
+ * timidity/playmidi.c: Fixed pan pot
+
+2000-04-12 Masanao Izumo <mo@goice.co.jp>
+
+ * timidity/alsa_a.c(PF_BUFF_FRAGM_OPT): Added the flag.
+
+2000-04-12 Eric A. Welsh <ewelsh@gpc.wustl.edu>
+
+ * timidity/recache.c: Bug fixed.
+
+2000-04-11 Takashi SHIRAI <shirai@pon.nintendo.co.jp>
+
+ * timidity/oss_a.c: Fixed for OSS version of !defined(SNDCTL_DSP_GETODELAY).
+
2000-04-10 Masanao Izumo <mo@goice.co.jp>
* Version 2.9.2 released.
Installation guide
Masanao Izumo <mo@goice.co.jp>
- Last updated on Sep.2.1999
+ Last updated on Apr.4.2000
==============================================================================
- This document describes how to install TiMidity++(version 2.6.0 or
+ This document describes how to install TiMidity++(version 2.9.2 or
later) for your UNIX-like machine. Methods for Macintosh are not
described in this document.
--prefix=PREFIX
Specifies the base of installing directory. By default,
PREFIX is "/usr/local/".
- Any files are installed in :
- PREFIX/bin : executable file
- PREFIX/lib/timidity : configuration files and patches
- PREFIX/man : online manual
+ Any files are installed in:
+ PREFIX/bin: executable files
+ PREFIX/share/timidity: configuration files and patches
+ PREFIX/lib/timidity: libraries and dynamic link interfaces.
+ PREFIX/man: online manuals
Example:
% sh configure --prefix=/opt/gnu
- # installs to /opt/gnu/bin, /opt/gnu/lib/timidity, /opt/gnu/man
+ # installs to /opt/gnu/bin, /opt/gnu/man, /opt/gnu/...
--x-includes=DIR
Specifies include directory of X library.
Specifies library directory of Tk.
(If you fail to detect it automatically, try to specify this.)
- --enable-audio
+ --enable-audio[=mode_list]
Enables TiMidity++ to play MIDI files.
If --enable-audio=no, TiMidity++ is only the MIDI-to-WAVE
- converter.
+ converter. You can specify multi-audio device from follows
+ (specify comma separated list):
+ default: Automatically select audio device. (default)
+ oss: OSS /dev/dsp
+ sun: SunOS /dev/audio
+ hpux: HPUX /dev/audio
+ irix: IRIX audio library
+ mme: OSF/1 MME
+ sb_dsp: BSD/OS 2.0 /dev/sb_dsp
+ w32: Windows MMS
+ alsa: ALSA pcm device
+ alib: HPUX network audio (Alib)
+ nas: NAS - Network Audio System
+ esd: EsounD
--enable-nas
Enables TiMidity++ to play MIDI files using NAS (Network Audio System).
--enable-esd
Enables TiMidity++ to play MIDI files using EsounD.
- --enable-dynamic
- Enables the feature of dynamic loading interface.
+ --enable-interface=[Comma separated interface list]
+ Specifies interface list (Comma separated). Choose interfaces
+ from follows.
+ ncurses,slang,motif,tcltk,emacs,vt100,xaw,xskin,gtk,w32gui,server
+ Note that
+ --enable-interface=INTERFACE1,INTERFACE2,...
+ equals as
+ --enable-INTERFACE1=yes --enable-INTERFACE2=yes ...
+
+ --enable-dynamic[=Comma separated interface list]
+ Specifies dynamic link interface list.
+ Note that
+ --enable-dynamic=INTERFACE1,INTERFACE2,...
+ equals as
+ --enable-INTERFACE1=dynamic --enable-INTERFACE2=dynamic ...
--enable-ncurses
Includes Ncurses interface. If you build this interface as dinamic
------------------------------
If configure failed or compile not complete successfully, edit
common.makefile, Makefile, and timidity.h to appropriate value.
-
-
+All of definition of variables are orverwrited by common.makefile.
3. make
-------
#define MAX_VOICES 256
\e$B$H$J$C$F$$$^$9!#\e(BDEFAULT_VOICES \e$B$O5/F0;~$NF1;~H/2;?t$G!"$3$NCM$O\e(B -p \e$B%*%W%7%g%s\e(B
-\e$B$rMQ$$$F\e(B 1\e$B!A\e(BMAX_VOICES \e$B$N?t$r@_Dj$9$k$3$H$,$G$-$^$9!#\e(B-iN \e$B%$%s%?!<%U%'!<%9$G$O\e(B
+\e$B$rMQ$$$F\e(B 1\e$B!A\e(BMAX_VOICES \e$B$N?t$r@_Dj$9$k$3$H$,$G$-$^$9!#\e(B-in \e$B%$%s%?!<%U%'!<%9$G$O\e(B
\e$B<B9T;~$KJQ2=$5$;$k$3$H$b$G$-$^$9!#\e(B
\e$B%Q%o!<$N$"$k%^%7%s$J$i!"%G%U%)%k%H$NF1;~H/2;?t$rA}$d$7$F\e(B
\e$B$H$J$C$F$$$^$9!#$3$l$O$3$N$^$^$G$$$$$G$7$g$&!#\e(B
\e$BJdB-\e(B: TiMidity \e$B$G$O!"2;$N2;DxJQ49$KIbF0>.?tE@?t$rMQ$$$:$K!"\e(B32 bit \e$B8GDj>.?tE@?t\e(B
-
+\e$B$rMQ$$$F7W;;$7$F$$$^$9!#\e(B
\e$B<!$K!"<+F0\e(B GUS/patch \e$B2;NLD4@a$N@_Dj$G$9!#%G%U%)%k%H$G$O\e(B
+05/08, 2000
+ * Version 2.9.3 released.
+ * Enable drum bends. This fix also enables drum chorus, mod-wheel,
+ portament, and other drum bend controls.
+
04/10, 2000
* Version 2.9.2 released.
\r
/* In VDS Macro AAA=BBB is not available. */\r
#define __W32__\r
-#define TIMID_VERSION "2.9.2"\r
+#define TIMID_VERSION "2.9.3"\r
#define DEFAULT_PATH ".\\"\r
#define AU_W32\r
#define WINSOCK\r
PACKAGE=TiMidity++
-VERSION=2.9.2
+VERSION=2.9.3
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
{ echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
AC_INIT(timidity/timidity.c)
SHELL=${CONFIG_SHELL-/bin/sh}
AC_CANONICAL_SYSTEM
-AM_INIT_AUTOMAKE(TiMidity++, 2.9.2, no-define)
+AM_INIT_AUTOMAKE(TiMidity++, 2.9.3, no-define)
dnl To use CONTAINS() macro (See acinclude.m4)
CONTAINS_INIT
rm -f *.o
rm -f *.$(so)
-tclIndex: $(TCLF)
+tclIndex: $(TCLSRCS)
rm -f tclIndex
echo 'auto_mkindex . *.tcl; exit' | $(WISH)
rm -f *.o
rm -f *.$(so)
-tclIndex: $(TCLF)
+tclIndex: $(TCLSRCS)
rm -f tclIndex
echo 'auto_mkindex . *.tcl; exit' | $(WISH)
playmidi.o: playmidi.c ../config.h timidity.h ../utils/support.h \
common.h ../libarc/url.h ../utils/mblock.h instrum.h playmidi.h \
readmidi.h output.h mix.h controls.h miditrace.h recache.h \
- ../libarc/arc.h reverb.h wrd.h aq.h tables.h
+ ../libarc/arc.h reverb.h wrd.h aq.h ../interface/soundspec.h \
+ tables.h
raw_a.o: raw_a.c ../config.h timidity.h ../utils/support.h output.h \
controls.h
rcp.o: rcp.c ../config.h timidity.h ../utils/support.h common.h \
timidity.o: timidity.c ../config.h ../interface.h timidity.h \
../utils/support.h common.h ../libarc/url.h ../utils/mblock.h \
instrum.h playmidi.h readmidi.h output.h controls.h tables.h \
- miditrace.h reverb.h recache.h ../libarc/arc.h \
- ../utils/strtab.h wrd.h mid.defs aq.h mix.h \
+ miditrace.h reverb.h ../interface/soundspec.h recache.h \
+ ../libarc/arc.h ../utils/strtab.h wrd.h mid.defs aq.h mix.h \
../libunimod/unimod.h
wave_a.o: wave_a.c ../config.h timidity.h ../utils/support.h output.h \
controls.h
#define dpm alsa_play_mode
PlayMode dpm = {
- DEFAULT_RATE, PE_16BIT|PE_SIGNED, PF_PCM_STREAM|PF_CAN_TRACE,
+ DEFAULT_RATE, PE_16BIT|PE_SIGNED, PF_PCM_STREAM|PF_CAN_TRACE|PF_BUFF_FRAGM_OPT,
-1,
{0}, /* default: get all the buffer fragments you can */
"ALSA pcm device", 's',
/* If this instrument will always be played on the same note,
and it's not looped, we can resample it now. */
+#ifdef DISALLOW_DRUM_BENDS
if (sp->note_to_use && !(sp->modes & MODES_LOOPING))
pre_resample(sp);
+#endif
#ifdef LOOKUP_HACK
/* Squash the 16-bit data into 8 bits. */
static int acntl(int request, void *arg)
{
+#ifndef SNDCTL_DSP_GETODELAY
+# ifdef SNDCTL_DSP_GETOSPACE
+ audio_buf_info info;
+# endif /* SNDCTL_DSP_GETOSPACE */
+ count_info cinfo;
+#endif /* SNDCTL_DSP_GETODELAY */
int i;
switch(request)
if(dpm.encoding & PE_16BIT) i >>= 1;
*((int *)arg) = i;
return 0;
+#else /* SNDCTL_DSP_GETODELAY */
+# ifdef SNDCTL_DSP_GETOSPACE
+ case PM_REQ_GETFILLABLE:
+ if(total_bytes <= 0 || ioctl(dpm.fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
+ return -1;
+ if (info.bytes > total_bytes) i = total_bytes;
+ else i = info.bytes;
+ if(!(dpm.encoding & PE_MONO)) i >>= 1;
+ if(dpm.encoding & PE_16BIT) i >>= 1;
+ *((int *)arg) = i;
+ return 0;
+
+ case PM_REQ_GETFILLED:
+ if(total_bytes <= 0 || ioctl(dpm.fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
+ return -1;
+ if (info.bytes > total_bytes) i = 0;
+ else i = total_bytes - info.bytes;
+ if(!(dpm.encoding & PE_MONO)) i >>= 1;
+ if(dpm.encoding & PE_16BIT) i >>= 1;
+ *((int *)arg) = i;
+ return 0;
+
+# endif /* SNDCTL_DSP_GETOSPACE */
+ case PM_REQ_GETSAMPLES:
+ if(total_bytes <= 0 || ioctl(dpm.fd, SNDCTL_DSP_GETOPTR, &cinfo) == -1)
+ return -1;
+ i = cinfo.bytes;
+ if(!(dpm.encoding & PE_MONO)) i >>= 1;
+ if(dpm.encoding & PE_16BIT) i >>= 1;
+ *((int *)arg) = i;
+ return 0;
#endif /* SNDCTL_DSP_GETODELAY */
}
return -1;
if(voice[j].status & VOICE_FREE || voice[j].cache != NULL)
continue;
/* skip notes that don't need resampling (most drums) */
- if (!voice[j].sample->sample_rate)
+ if (voice[j].sample->note_to_use)
continue;
if(voice[j].status & ~(VOICE_ON | VOICE_DIE | VOICE_SUSTAINED))
{
if(voice[j].status & ~(VOICE_ON | VOICE_SUSTAINED))
{
/* continue protecting non-resample decays */
- if (voice[j].status & ~(VOICE_DIE) && !voice[j].sample->sample_rate)
+ if (voice[j].status & ~(VOICE_DIE) && voice[j].sample->note_to_use)
continue;
/* choose note which has been on the shortest amount of time */
for(j = 0; j < i; j++)
{
if(voice[j].status & VOICE_FREE ||
- (!voice[j].sample->sample_rate && ISDRUMCHANNEL(voice[j].channel)))
+ (voice[j].sample->note_to_use && ISDRUMCHANNEL(voice[j].channel)))
continue;
if(voice[j].status & ~(VOICE_ON | VOICE_DIE | VOICE_SUSTAINED))
{
/* continue protecting drum decays */
if (voice[j].status & ~(VOICE_DIE) &&
- (!voice[j].sample->sample_rate && ISDRUMCHANNEL(voice[j].channel)))
+ (voice[j].sample->note_to_use && ISDRUMCHANNEL(voice[j].channel)))
continue;
/* find lowest volume */
v = voice[j].left_mix;
for(j = 0; j < i; j++)
{
if(voice[j].status & VOICE_FREE ||
- (!voice[j].sample->sample_rate && ISDRUMCHANNEL(voice[j].channel)))
+ (voice[j].sample->note_to_use && ISDRUMCHANNEL(voice[j].channel)))
continue;
/* find lowest volume */
for(i = 0; i < nv; i++)
{
if(voice[i].status & ~(VOICE_ON | VOICE_DIE) &&
- !(!voice[i].sample->sample_rate && ISDRUMCHANNEL(voice[i].channel)))
+ !(voice[i].sample->note_to_use && ISDRUMCHANNEL(voice[i].channel)))
{
v = voice[i].left_mix;
if((voice[i].panned==PANNED_MYSTERY) && (voice[i].right_mix>v))
static void start_note(MidiEvent *e, int i, int vid, int cnt)
{
- int j, ch, note;
+ int j, ch, note, pan;
ch = e->channel;
voice[i].vibrato_sample_increment[j]=0;
/* Pan */
+ if(channel[ch].panning != NO_PANNING) pan = channel[ch].panning;
+ else pan = 64;
if(ISDRUMCHANNEL(ch) &&
channel[ch].drums[note] != NULL &&
channel[ch].drums[note]->drum_panning != NO_PANNING)
- voice[i].panning = channel[ch].drums[note]->drum_panning;
- else if(channel[ch].panning != NO_PANNING)
- voice[i].panning = channel[ch].panning;
+ pan += channel[ch].drums[note]->drum_panning - 64;
else
- voice[i].panning = voice[i].sample->panning;
+ pan += voice[i].sample->panning - 64;
+ if (pan > 127) pan = 127;
+ if (pan < 0) pan = 0;
+ voice[i].panning = pan;
voice[i].porta_control_counter = 0;
if(channel[ch].portamento && !channel[ch].porta_control_ratio)
ctl_mode_event(CTLE_PANNING, 1, ch, channel[ch].panning);
}
start_note(e, v, vid, nv - i - 1);
- if((channel[ch].chorus_level || opt_surround_chorus) &&
- voice[v].sample->sample_rate)
+ if((channel[ch].chorus_level || opt_surround_chorus))
{
if(opt_surround_chorus)
new_chorus_voice_alternate(v, channel[ch].chorus_level);
if ((voice[i].channel==c) &&
(voice[i].status & (VOICE_ON | VOICE_SUSTAINED)))
{
+ /* adjust pan to include drum/sample pan offsets */
+ if(ISDRUMCHANNEL(c) &&
+ channel[c].drums[i] != NULL &&
+ channel[c].drums[i]->drum_panning != NO_PANNING)
+ pan += channel[c].drums[i]->drum_panning - 64;
+ else
+ pan += voice[i].sample->panning - 64;
+ if (pan > 127) pan = 127;
+ if (pan < 0) pan = 0;
+
/* Hack to handle -EFchorus=2 in a "reasonable" way */
if((channel[c].chorus_level || opt_surround_chorus) &&
- voice[i].sample->sample_rate &&
voice[i].chorus_link != i)
{
int v1, v2;
if(pan == 0xFF)
return;
+ /* slide the pan by the channel pan offset */
+ if(channel[ch].panning != NO_PANNING)
+ pan += channel[ch].panning - 64;
+ if (pan > 127) pan = 127;
+ if (pan < 0) pan = 0;
+
for(i = 0; i < uv; i++)
if(voice[i].channel == ch &&
voice[i].note == note &&
int get_chorus_level(int ch)
{
+#ifdef DISALLOW_DRUM_BENDS
if(ISDRUMCHANNEL(ch))
return 0; /* Not supported drum channel chorus */
+#endif
if(opt_chorus_control == 1)
return channel[ch].chorus_level;
return -opt_chorus_control;
for(j = 0; j < voices; j++)
{
if(voice[j].status & ~(VOICE_ON | VOICE_DIE) &&
- !(!voice[j].sample->sample_rate &&
+ !(voice[j].sample->note_to_use &&
ISDRUMCHANNEL(voice[j].channel)))
{
v = voice[j].left_mix;
if((voice[i].status & ~(VOICE_ON|VOICE_SUSTAINED) &&
!(voice[i].status & ~(VOICE_DIE) &&
- !voice[i].sample->sample_rate)))
+ voice[i].sample->note_to_use)))
kill_nv++;
}
}
}
- /* GS program change */
- /* I could not find any documentation on this, so I reverse engineered
- which bytes do what from midi I have. It appears to work correctly. */
- if(len == 11 &&
- val[0] == 0x41 && /* Roland ID */
- val[1] == 0x10 && /* Device ID */
- val[2] == 0x42 && /* GS Model ID */
- val[3] == 0x12 && /* Data Set Command */
- val[4] == 0x40 && /* I wish I knew what this was... */
- (val[5] >= 0x10 && val[5] < 0x20)) /* channel command */
- {
- uint8 p; /* Channel part number [0..15] */
-
- p = val[5] & 0x0F;
- if(p == 0)
- p = 9;
- else if(p <= 9)
- p--;
- p = MERGE_CHANNEL_PORT(p);
-
- MIDIEVENT(at, ME_TONE_BANK_MSB, p, val[7], 0);
- MIDIEVENT(at, ME_TONE_BANK_LSB, p, 1, 0); /* assume SC-55 ??? */
- MIDIEVENT(at, ME_PROGRAM, p, val[8], 0);
-
- num_events = 2;
- }
-
/* GS bank+program change */
/* I could not find any documentation on this, so I reverse engineered
which bytes do what from midi I have. It appears to work correctly. */
v1 = (int32)src[(ofs>>FRACTION_BITS)]; \
v2 = (int32)src[(ofs>>FRACTION_BITS)+1]; \
if(((ofs-(1L<<FRACTION_BITS))<ls)||((ofs+(2L<<FRACTION_BITS))>le)){ \
- *dest++ = (sample_t)(v1 + (((v2-v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS)); \
+ dest[i] = (sample_t)(v1 + (((v2-v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS)); \
}else{ \
ofsd=ofs; \
v0 = (int32)src[(ofs>>FRACTION_BITS)-1]; \
ofs>>FRACTION_BITS)*(ofs-(2L<<FRACTION_BITS)) \
>>FRACTION_BITS))*((1L<<FRACTION_BITS)-ofs))+v2) \
/(6L<<FRACTION_BITS); \
- *dest++ = (v1 > 32767)? 32767: ((v1 < -32768)? -32768: v1); \
+ dest[i] = (v1 > 32767)? 32767: ((v1 < -32768)? -32768: v1); \
ofs = ofsd; \
}
#elif defined(LAGRANGE_INTERPOLATION)
if(sp->vibrato_control_ratio ||
(sp->modes & MODES_PINGPONG) ||
- sp->sample_rate == 0)
- return NULL;
+ (sp->sample_rate == play_mode->rate &&
+ sp->root_freq == freq_table[sp->note_to_use]))
+ return NULL;
addr = sp_hash(sp, note) % HASH_TABLE_SIZE;
p = cache_hash_table[addr];
channel[ch].portamento ||
(vp->sample->modes & MODES_PINGPONG) ||
vp->orig_frequency != vp->frequency ||
- vp->sample->sample_rate == 0)
- return;
+ (vp->sample->sample_rate == play_mode->rate &&
+ vp->sample->root_freq == freq_table[vp->sample->note_to_use]))
+ return;
note = vp->note;
return;
sp = p->sp;
- if(sp->sample_rate == 0)
+ if(sp->sample_rate == play_mode->rate &&
+ sp->root_freq == freq_table[sp->note_to_use])
return;
sample_start = channel_note_table[ch].on[note];
Voice *vp=&voice[v];
int mode;
- if(!(vp->sample->sample_rate))
+ if(vp->sample->sample_rate == play_mode->rate &&
+ vp->sample->root_freq == freq_table[vp->sample->note_to_use] &&
+ (vp->frequency == vp->orig_frequency || vp->porta_control_ratio))
{
int32 ofs;
sp->loop_end = (int32)(sp->loop_end * a);
free(sp->data);
sp->data = (sample_t *) newdata;
+/*
sp->sample_rate = 0;
+*/
+ sp->root_freq = freq_table[(int) (sp->note_to_use)];
+ sp->sample_rate = play_mode->rate;
+ sp->low_freq = freq_table[0];
+ sp->high_freq = freq_table[127];
}
sample->sample_rate,
play_mode->rate);
+#ifdef DISALLOW_DRUM_BENDS
/* resample it if possible */
if (sample->note_to_use && !(sample->modes & MODES_LOOPING))
pre_resample(sample);
+#endif
#ifdef LOOKUP_HACK
/* squash the 16-bit data into 8 bits. */