Moved all files one dir upwards (should've done that long ago)
This commit is contained in:
30
project/jni/sdl_mixer/native_midi_gpl/README
Normal file
30
project/jni/sdl_mixer/native_midi_gpl/README
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
Unfortunately, the code for the native MIDI support on Linux is derived
|
||||
from source under the GNU General Public License, and not the GNU LGPL.
|
||||
Therefore, it's not built by default.
|
||||
|
||||
Native Midi support for Linux should work on FreeBSD too ( I can not test it ).
|
||||
|
||||
Midi device can be selected with enviroment variable SDL_NATIVE_MUSIC, it can be
|
||||
one of following values:
|
||||
GUS - GravisUltrasound
|
||||
AWE - SoundBlaster AWE32
|
||||
FM - FreqentionModulation SoundBlaster Compatible
|
||||
OPL3 - Yamaha OPL/3
|
||||
EXT - External MIDI port
|
||||
|
||||
External MIDI port can be set with env. SDL_NATIVE_MUSIC_EXT (SDL_NATIVE_MUSIC_EXT="1").
|
||||
|
||||
Autoselect priority:
|
||||
1. GUS
|
||||
2. AWE
|
||||
3. use Timidity
|
||||
4. FM
|
||||
5. EXT
|
||||
|
||||
Also if you want use FM befor Timidity set variable SDL_NATIVE_MUSIC="FM" or edit
|
||||
source code native_midi_lnx.c( return value in function synth_setup, by autoselect
|
||||
FM should return 1).
|
||||
For using FM: files drums.sb drums.o3 std.sb std.o3 should be moved to /etc/ dir
|
||||
( or symlink created ).
|
||||
|
||||
490
project/jni/sdl_mixer/native_midi_gpl/awe_voice.h
Normal file
490
project/jni/sdl_mixer/native_midi_gpl/awe_voice.h
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* sound/awe_voice.h
|
||||
*
|
||||
* Voice information definitions for the low level driver for the
|
||||
* AWE32/Sound Blaster 32 wave table synth.
|
||||
* version 0.4.2c; Oct. 7, 1997
|
||||
*
|
||||
* Copyright (C) 1996,1997 Takashi Iwai
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef AWE_VOICE_H
|
||||
#define AWE_VOICE_H
|
||||
|
||||
#ifndef SAMPLE_TYPE_AWE32
|
||||
#define SAMPLE_TYPE_AWE32 0x20
|
||||
#endif
|
||||
|
||||
#ifndef _PATCHKEY
|
||||
#define _PATCHKEY(id) ((id<<8)|0xfd)
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* patch information record
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
/* patch interface header: 16 bytes */
|
||||
typedef struct awe_patch_info {
|
||||
short key; /* use AWE_PATCH here */
|
||||
#define AWE_PATCH _PATCHKEY(0x07)
|
||||
|
||||
short device_no; /* synthesizer number */
|
||||
unsigned short sf_id; /* file id (should be zero) */
|
||||
short optarg; /* optional argument */
|
||||
int len; /* data length (without this header) */
|
||||
|
||||
short type; /* patch operation type */
|
||||
#define AWE_LOAD_INFO 0 /* awe_voice_rec */
|
||||
#define AWE_LOAD_DATA 1 /* awe_sample_info */
|
||||
#define AWE_OPEN_PATCH 2 /* awe_open_parm */
|
||||
#define AWE_CLOSE_PATCH 3 /* none */
|
||||
#define AWE_UNLOAD_PATCH 4 /* none */
|
||||
#define AWE_REPLACE_DATA 5 /* awe_sample_info (optarg=#channels)*/
|
||||
#define AWE_MAP_PRESET 6 /* awe_voice_map */
|
||||
#define AWE_LOAD_CHORUS_FX 0x10 /* awe_chorus_fx_rec (optarg=mode) */
|
||||
#define AWE_LOAD_REVERB_FX 0x11 /* awe_reverb_fx_rec (optarg=mode) */
|
||||
|
||||
short reserved; /* word alignment data */
|
||||
|
||||
/* the actual patch data begins after this */
|
||||
#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
|
||||
char data[0];
|
||||
#endif
|
||||
} awe_patch_info;
|
||||
|
||||
/*#define AWE_PATCH_INFO_SIZE 16*/
|
||||
#define AWE_PATCH_INFO_SIZE sizeof(awe_patch_info)
|
||||
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* open patch
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
#define AWE_PATCH_NAME_LEN 32
|
||||
|
||||
typedef struct _awe_open_parm {
|
||||
unsigned short type; /* sample type */
|
||||
#define AWE_PAT_TYPE_MISC 0
|
||||
#define AWE_PAT_TYPE_GM 1
|
||||
#define AWE_PAT_TYPE_GS 2
|
||||
#define AWE_PAT_TYPE_MT32 3
|
||||
#define AWE_PAT_TYPE_XG 4
|
||||
#define AWE_PAT_TYPE_SFX 5
|
||||
#define AWE_PAT_TYPE_GUS 6
|
||||
#define AWE_PAT_TYPE_MAP 7
|
||||
|
||||
#define AWE_PAT_LOCKED 0x100 /* lock the samples */
|
||||
|
||||
short reserved;
|
||||
char name[AWE_PATCH_NAME_LEN];
|
||||
} awe_open_parm;
|
||||
|
||||
/*#define AWE_OPEN_PARM_SIZE 28*/
|
||||
#define AWE_OPEN_PARM_SIZE sizeof(awe_open_parm)
|
||||
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* raw voice information record
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
/* wave table envelope & effect parameters to control EMU8000 */
|
||||
typedef struct _awe_voice_parm {
|
||||
unsigned short moddelay; /* modulation delay (0x8000) */
|
||||
unsigned short modatkhld; /* modulation attack & hold time (0x7f7f) */
|
||||
unsigned short moddcysus; /* modulation decay & sustain (0x7f7f) */
|
||||
unsigned short modrelease; /* modulation release time (0x807f) */
|
||||
short modkeyhold, modkeydecay; /* envelope change per key (not used) */
|
||||
unsigned short voldelay; /* volume delay (0x8000) */
|
||||
unsigned short volatkhld; /* volume attack & hold time (0x7f7f) */
|
||||
unsigned short voldcysus; /* volume decay & sustain (0x7f7f) */
|
||||
unsigned short volrelease; /* volume release time (0x807f) */
|
||||
short volkeyhold, volkeydecay; /* envelope change per key (not used) */
|
||||
unsigned short lfo1delay; /* LFO1 delay (0x8000) */
|
||||
unsigned short lfo2delay; /* LFO2 delay (0x8000) */
|
||||
unsigned short pefe; /* modulation pitch & cutoff (0x0000) */
|
||||
unsigned short fmmod; /* LFO1 pitch & cutoff (0x0000) */
|
||||
unsigned short tremfrq; /* LFO1 volume & freq (0x0000) */
|
||||
unsigned short fm2frq2; /* LFO2 pitch & freq (0x0000) */
|
||||
unsigned char cutoff; /* initial cutoff (0xff) */
|
||||
unsigned char filterQ; /* initial filter Q [0-15] (0x0) */
|
||||
unsigned char chorus; /* chorus send (0x00) */
|
||||
unsigned char reverb; /* reverb send (0x00) */
|
||||
unsigned short reserved[4]; /* not used */
|
||||
} awe_voice_parm;
|
||||
|
||||
#define AWE_VOICE_PARM_SIZE 48
|
||||
|
||||
|
||||
/* wave table parameters: 92 bytes */
|
||||
typedef struct _awe_voice_info {
|
||||
unsigned short sf_id; /* file id (should be zero) */
|
||||
unsigned short sample; /* sample id */
|
||||
int start, end; /* sample offset correction */
|
||||
int loopstart, loopend; /* loop offset correction */
|
||||
short rate_offset; /* sample rate pitch offset */
|
||||
unsigned short mode; /* sample mode */
|
||||
#define AWE_MODE_ROMSOUND 0x8000
|
||||
#define AWE_MODE_STEREO 1
|
||||
#define AWE_MODE_LOOPING 2
|
||||
#define AWE_MODE_NORELEASE 4 /* obsolete */
|
||||
#define AWE_MODE_INIT_PARM 8
|
||||
|
||||
short root; /* midi root key */
|
||||
short tune; /* pitch tuning (in cents) */
|
||||
char low, high; /* key note range */
|
||||
char vellow, velhigh; /* velocity range */
|
||||
char fixkey, fixvel; /* fixed key, velocity */
|
||||
char pan, fixpan; /* panning, fixed panning */
|
||||
short exclusiveClass; /* exclusive class (0 = none) */
|
||||
unsigned char amplitude; /* sample volume (127 max) */
|
||||
unsigned char attenuation; /* attenuation (0.375dB) */
|
||||
short scaleTuning; /* pitch scale tuning(%), normally 100 */
|
||||
awe_voice_parm parm; /* voice envelope parameters */
|
||||
short index; /* internal index (set by driver) */
|
||||
} awe_voice_info;
|
||||
|
||||
/*#define AWE_VOICE_INFO_SIZE 92*/
|
||||
#define AWE_VOICE_INFO_SIZE sizeof(awe_voice_info)
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
/* The info entry of awe_voice_rec is changed from 0 to 1
|
||||
* for some compilers refusing zero size array.
|
||||
* Due to this change, sizeof(awe_voice_rec) becomes different
|
||||
* from older versions.
|
||||
* Use AWE_VOICE_REC_SIZE instead.
|
||||
*/
|
||||
|
||||
/* instrument info header: 4 bytes */
|
||||
typedef struct _awe_voice_rec_hdr {
|
||||
unsigned char bank; /* midi bank number */
|
||||
unsigned char instr; /* midi preset number */
|
||||
char nvoices; /* number of voices */
|
||||
char write_mode; /* write mode; normally 0 */
|
||||
#define AWE_WR_APPEND 0 /* append anyway */
|
||||
#define AWE_WR_EXCLUSIVE 1 /* skip if already exists */
|
||||
#define AWE_WR_REPLACE 2 /* replace if already exists */
|
||||
} awe_voice_rec_hdr;
|
||||
|
||||
/*#define AWE_VOICE_REC_SIZE 4*/
|
||||
#define AWE_VOICE_REC_SIZE sizeof(awe_voice_rec_hdr)
|
||||
|
||||
/* the standard patch structure for one sample */
|
||||
typedef struct _awe_voice_rec_patch {
|
||||
awe_patch_info patch;
|
||||
awe_voice_rec_hdr hdr;
|
||||
awe_voice_info info;
|
||||
} awe_voice_rec_patch;
|
||||
|
||||
|
||||
/* obsolete data type */
|
||||
#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
|
||||
#define AWE_INFOARRAY_SIZE 0
|
||||
#else
|
||||
#define AWE_INFOARRAY_SIZE 1
|
||||
#endif
|
||||
|
||||
typedef struct _awe_voice_rec {
|
||||
unsigned char bank; /* midi bank number */
|
||||
unsigned char instr; /* midi preset number */
|
||||
short nvoices; /* number of voices */
|
||||
/* voice information follows here */
|
||||
awe_voice_info info[AWE_INFOARRAY_SIZE];
|
||||
} awe_voice_rec;
|
||||
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* sample wave information
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
/* wave table sample header: 32 bytes */
|
||||
typedef struct awe_sample_info {
|
||||
unsigned short sf_id; /* file id (should be zero) */
|
||||
unsigned short sample; /* sample id */
|
||||
int start, end; /* start & end offset */
|
||||
int loopstart, loopend; /* loop start & end offset */
|
||||
int size; /* size (0 = ROM) */
|
||||
short checksum_flag; /* use check sum = 1 */
|
||||
unsigned short mode_flags; /* mode flags */
|
||||
#define AWE_SAMPLE_8BITS 1 /* wave data is 8bits */
|
||||
#define AWE_SAMPLE_UNSIGNED 2 /* wave data is unsigned */
|
||||
#define AWE_SAMPLE_NO_BLANK 4 /* no blank loop is attached */
|
||||
#define AWE_SAMPLE_SINGLESHOT 8 /* single-shot w/o loop */
|
||||
#define AWE_SAMPLE_BIDIR_LOOP 16 /* bidirectional looping */
|
||||
#define AWE_SAMPLE_STEREO_LEFT 32 /* stereo left sound */
|
||||
#define AWE_SAMPLE_STEREO_RIGHT 64 /* stereo right sound */
|
||||
#define AWE_SAMPLE_REVERSE_LOOP 128 /* reverse looping */
|
||||
unsigned int checksum; /* check sum */
|
||||
#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
|
||||
unsigned short data[0]; /* sample data follows here */
|
||||
#endif
|
||||
} awe_sample_info;
|
||||
|
||||
/*#define AWE_SAMPLE_INFO_SIZE 32*/
|
||||
#define AWE_SAMPLE_INFO_SIZE sizeof(awe_sample_info)
|
||||
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* voice preset mapping
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
typedef struct awe_voice_map {
|
||||
int map_bank, map_instr, map_key; /* key = -1 means all keys */
|
||||
int src_bank, src_instr, src_key;
|
||||
} awe_voice_map;
|
||||
|
||||
#define AWE_VOICE_MAP_SIZE sizeof(awe_voice_map)
|
||||
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* awe hardware controls
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
#define _AWE_DEBUG_MODE 0x00
|
||||
#define _AWE_REVERB_MODE 0x01
|
||||
#define _AWE_CHORUS_MODE 0x02
|
||||
#define _AWE_REMOVE_LAST_SAMPLES 0x03
|
||||
#define _AWE_INITIALIZE_CHIP 0x04
|
||||
#define _AWE_SEND_EFFECT 0x05
|
||||
#define _AWE_TERMINATE_CHANNEL 0x06
|
||||
#define _AWE_TERMINATE_ALL 0x07
|
||||
#define _AWE_INITIAL_VOLUME 0x08
|
||||
#define _AWE_INITIAL_ATTEN _AWE_INITIAL_VOLUME
|
||||
#define _AWE_RESET_CHANNEL 0x09
|
||||
#define _AWE_CHANNEL_MODE 0x0a
|
||||
#define _AWE_DRUM_CHANNELS 0x0b
|
||||
#define _AWE_MISC_MODE 0x0c
|
||||
#define _AWE_RELEASE_ALL 0x0d
|
||||
#define _AWE_NOTEOFF_ALL 0x0e
|
||||
#define _AWE_CHN_PRESSURE 0x0f
|
||||
/*#define _AWE_GET_CURRENT_MODE 0x10*/
|
||||
#define _AWE_EQUALIZER 0x11
|
||||
/*#define _AWE_GET_MISC_MODE 0x12*/
|
||||
/*#define _AWE_GET_FONTINFO 0x13*/
|
||||
|
||||
#define _AWE_MODE_FLAG 0x80
|
||||
#define _AWE_COOKED_FLAG 0x40 /* not supported */
|
||||
#define _AWE_MODE_VALUE_MASK 0x3F
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
#define _AWE_SET_CMD(p,dev,voice,cmd,p1,p2) \
|
||||
{((char*)(p))[0] = SEQ_PRIVATE;\
|
||||
((char*)(p))[1] = dev;\
|
||||
((char*)(p))[2] = _AWE_MODE_FLAG|(cmd);\
|
||||
((char*)(p))[3] = voice;\
|
||||
((unsigned short*)(p))[2] = p1;\
|
||||
((unsigned short*)(p))[3] = p2;}
|
||||
|
||||
/* buffered access */
|
||||
#define _AWE_CMD(dev, voice, cmd, p1, p2) \
|
||||
{_SEQ_NEEDBUF(8);\
|
||||
_AWE_SET_CMD(_seqbuf + _seqbufptr, dev, voice, cmd, p1, p2);\
|
||||
_SEQ_ADVBUF(8);}
|
||||
|
||||
/* direct access */
|
||||
#define _AWE_CMD_NOW(seqfd,dev,voice,cmd,p1,p2) \
|
||||
{struct seq_event_rec tmp;\
|
||||
_AWE_SET_CMD(&tmp, dev, voice, cmd, p1, p2);\
|
||||
ioctl(seqfd, SNDCTL_SEQ_OUTOFBAND, &tmp);}
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
/* set debugging mode */
|
||||
#define AWE_DEBUG_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_DEBUG_MODE, p1, 0)
|
||||
/* set reverb mode; from 0 to 7 */
|
||||
#define AWE_REVERB_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_REVERB_MODE, p1, 0)
|
||||
/* set chorus mode; from 0 to 7 */
|
||||
#define AWE_CHORUS_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_CHORUS_MODE, p1, 0)
|
||||
|
||||
/* reset channel */
|
||||
#define AWE_RESET_CHANNEL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 0, 0)
|
||||
#define AWE_RESET_CONTROL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 1, 0)
|
||||
|
||||
/* send an effect to all layers */
|
||||
#define AWE_SEND_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,type,value)
|
||||
#define AWE_ADD_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x80),value)
|
||||
#define AWE_UNSET_EFFECT(dev,voice,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x40),0)
|
||||
/* send an effect to a layer */
|
||||
#define AWE_SEND_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)),value)
|
||||
#define AWE_ADD_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x80),value)
|
||||
#define AWE_UNSET_LAYER_EFFECT(dev,voice,layer,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x40),0)
|
||||
|
||||
/* terminate sound on the channel/voice */
|
||||
#define AWE_TERMINATE_CHANNEL(dev,voice) _AWE_CMD(dev,voice,_AWE_TERMINATE_CHANNEL,0,0)
|
||||
/* terminate all sounds */
|
||||
#define AWE_TERMINATE_ALL(dev) _AWE_CMD(dev, 0, _AWE_TERMINATE_ALL, 0, 0)
|
||||
/* release all sounds (w/o sustain effect) */
|
||||
#define AWE_RELEASE_ALL(dev) _AWE_CMD(dev, 0, _AWE_RELEASE_ALL, 0, 0)
|
||||
/* note off all sounds (w sustain effect) */
|
||||
#define AWE_NOTEOFF_ALL(dev) _AWE_CMD(dev, 0, _AWE_NOTEOFF_ALL, 0, 0)
|
||||
|
||||
/* set initial attenuation */
|
||||
#define AWE_INITIAL_VOLUME(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 0)
|
||||
#define AWE_INITIAL_ATTEN AWE_INITIAL_VOLUME
|
||||
/* relative attenuation */
|
||||
#define AWE_SET_ATTEN(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 1)
|
||||
|
||||
/* set channel playing mode; mode=0/1/2 */
|
||||
#define AWE_SET_CHANNEL_MODE(dev,mode) _AWE_CMD(dev, 0, _AWE_CHANNEL_MODE, mode, 0)
|
||||
#define AWE_PLAY_INDIRECT 0 /* indirect voice mode (default) */
|
||||
#define AWE_PLAY_MULTI 1 /* multi note voice mode */
|
||||
#define AWE_PLAY_DIRECT 2 /* direct single voice mode */
|
||||
#define AWE_PLAY_MULTI2 3 /* sequencer2 mode; used internally */
|
||||
|
||||
/* set drum channel mask; channels is 32bit long value */
|
||||
#define AWE_DRUM_CHANNELS(dev,channels) _AWE_CMD(dev, 0, _AWE_DRUM_CHANNELS, ((channels) & 0xffff), ((channels) >> 16))
|
||||
|
||||
/* set bass and treble control; values are from 0 to 11 */
|
||||
#define AWE_EQUALIZER(dev,bass,treble) _AWE_CMD(dev, 0, _AWE_EQUALIZER, bass, treble)
|
||||
|
||||
/* remove last loaded samples */
|
||||
#define AWE_REMOVE_LAST_SAMPLES(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_REMOVE_LAST_SAMPLES, 0, 0)
|
||||
/* initialize emu8000 chip */
|
||||
#define AWE_INITIALIZE_CHIP(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_INITIALIZE_CHIP, 0, 0)
|
||||
|
||||
/* set miscellaneous modes; meta command */
|
||||
#define AWE_MISC_MODE(dev,mode,value) _AWE_CMD(dev, 0, _AWE_MISC_MODE, mode, value)
|
||||
/* exclusive sound off; 1=off */
|
||||
#define AWE_EXCLUSIVE_SOUND(dev,mode) AWE_MISC_MODE(dev,AWE_MD_EXCLUSIVE_SOUND,mode)
|
||||
/* default GUS bank number */
|
||||
#define AWE_SET_GUS_BANK(dev,bank) AWE_MISC_MODE(dev,AWE_MD_GUS_BANK,bank)
|
||||
/* change panning position in realtime; 0=don't 1=do */
|
||||
#define AWE_REALTIME_PAN(dev,mode) AWE_MISC_MODE(dev,AWE_MD_REALTIME_PAN,mode)
|
||||
|
||||
/* extended pressure controls; not portable with other sound drivers */
|
||||
#define AWE_KEY_PRESSURE(dev,ch,note,vel) SEQ_START_NOTE(dev,ch,(note)+128,vel)
|
||||
#define AWE_CHN_PRESSURE(dev,ch,vel) _AWE_CMD(dev,ch,_AWE_CHN_PRESSURE,vel,0)
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
/* reverb mode parameters */
|
||||
#define AWE_REVERB_ROOM1 0
|
||||
#define AWE_REVERB_ROOM2 1
|
||||
#define AWE_REVERB_ROOM3 2
|
||||
#define AWE_REVERB_HALL1 3
|
||||
#define AWE_REVERB_HALL2 4
|
||||
#define AWE_REVERB_PLATE 5
|
||||
#define AWE_REVERB_DELAY 6
|
||||
#define AWE_REVERB_PANNINGDELAY 7
|
||||
#define AWE_REVERB_PREDEFINED 8
|
||||
/* user can define reverb modes up to 32 */
|
||||
#define AWE_REVERB_NUMBERS 32
|
||||
|
||||
typedef struct awe_reverb_fx_rec {
|
||||
unsigned short parms[28];
|
||||
} awe_reverb_fx_rec;
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
/* chorus mode parameters */
|
||||
#define AWE_CHORUS_1 0
|
||||
#define AWE_CHORUS_2 1
|
||||
#define AWE_CHORUS_3 2
|
||||
#define AWE_CHORUS_4 3
|
||||
#define AWE_CHORUS_FEEDBACK 4
|
||||
#define AWE_CHORUS_FLANGER 5
|
||||
#define AWE_CHORUS_SHORTDELAY 6
|
||||
#define AWE_CHORUS_SHORTDELAY2 7
|
||||
#define AWE_CHORUS_PREDEFINED 8
|
||||
/* user can define chorus modes up to 32 */
|
||||
#define AWE_CHORUS_NUMBERS 32
|
||||
|
||||
typedef struct awe_chorus_fx_rec {
|
||||
unsigned short feedback; /* feedback level (0xE600-0xE6FF) */
|
||||
unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */
|
||||
unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */
|
||||
unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
|
||||
unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */
|
||||
} awe_chorus_fx_rec;
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
/* misc mode types */
|
||||
enum {
|
||||
/* 0*/ AWE_MD_EXCLUSIVE_OFF, /* obsolete */
|
||||
/* 1*/ AWE_MD_EXCLUSIVE_ON, /* obsolete */
|
||||
/* 2*/ AWE_MD_VERSION, /* read only */
|
||||
/* 3*/ AWE_MD_EXCLUSIVE_SOUND, /* ignored */
|
||||
/* 4*/ AWE_MD_REALTIME_PAN, /* 0/1: do realtime pan change (default=1) */
|
||||
/* 5*/ AWE_MD_GUS_BANK, /* bank number for GUS patches (default=0) */
|
||||
/* 6*/ AWE_MD_KEEP_EFFECT, /* 0/1: keep effect values, (default=0) */
|
||||
/* 7*/ AWE_MD_ZERO_ATTEN, /* attenuation of max volume (default=32) */
|
||||
/* 8*/ AWE_MD_CHN_PRIOR, /* 0/1: set MIDI channel priority mode (default=1) */
|
||||
/* 9*/ AWE_MD_MOD_SENSE, /* integer: modwheel sensitivity (def=18) */
|
||||
/*10*/ AWE_MD_DEF_PRESET, /* integer: default preset number (def=0) */
|
||||
/*11*/ AWE_MD_DEF_BANK, /* integer: default bank number (def=0) */
|
||||
/*12*/ AWE_MD_DEF_DRUM, /* integer: default drumset number (def=0) */
|
||||
/*13*/ AWE_MD_TOGGLE_DRUM_BANK, /* 0/1: toggle drum flag with bank# (def=0) */
|
||||
AWE_MD_END,
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
/* effect parameters */
|
||||
enum {
|
||||
|
||||
/* modulation envelope parameters */
|
||||
/* 0*/ AWE_FX_ENV1_DELAY, /* WORD: ENVVAL */
|
||||
/* 1*/ AWE_FX_ENV1_ATTACK, /* BYTE: up ATKHLD */
|
||||
/* 2*/ AWE_FX_ENV1_HOLD, /* BYTE: lw ATKHLD */
|
||||
/* 3*/ AWE_FX_ENV1_DECAY, /* BYTE: lw DCYSUS */
|
||||
/* 4*/ AWE_FX_ENV1_RELEASE, /* BYTE: lw DCYSUS */
|
||||
/* 5*/ AWE_FX_ENV1_SUSTAIN, /* BYTE: up DCYSUS */
|
||||
/* 6*/ AWE_FX_ENV1_PITCH, /* BYTE: up PEFE */
|
||||
/* 7*/ AWE_FX_ENV1_CUTOFF, /* BYTE: lw PEFE */
|
||||
|
||||
/* volume envelope parameters */
|
||||
/* 8*/ AWE_FX_ENV2_DELAY, /* WORD: ENVVOL */
|
||||
/* 9*/ AWE_FX_ENV2_ATTACK, /* BYTE: up ATKHLDV */
|
||||
/*10*/ AWE_FX_ENV2_HOLD, /* BYTE: lw ATKHLDV */
|
||||
/*11*/ AWE_FX_ENV2_DECAY, /* BYTE: lw DCYSUSV */
|
||||
/*12*/ AWE_FX_ENV2_RELEASE, /* BYTE: lw DCYSUSV */
|
||||
/*13*/ AWE_FX_ENV2_SUSTAIN, /* BYTE: up DCYSUSV */
|
||||
|
||||
/* LFO1 (tremolo & vibrato) parameters */
|
||||
/*14*/ AWE_FX_LFO1_DELAY, /* WORD: LFO1VAL */
|
||||
/*15*/ AWE_FX_LFO1_FREQ, /* BYTE: lo TREMFRQ */
|
||||
/*16*/ AWE_FX_LFO1_VOLUME, /* BYTE: up TREMFRQ */
|
||||
/*17*/ AWE_FX_LFO1_PITCH, /* BYTE: up FMMOD */
|
||||
/*18*/ AWE_FX_LFO1_CUTOFF, /* BYTE: lo FMMOD */
|
||||
|
||||
/* LFO2 (vibrato) parameters */
|
||||
/*19*/ AWE_FX_LFO2_DELAY, /* WORD: LFO2VAL */
|
||||
/*20*/ AWE_FX_LFO2_FREQ, /* BYTE: lo FM2FRQ2 */
|
||||
/*21*/ AWE_FX_LFO2_PITCH, /* BYTE: up FM2FRQ2 */
|
||||
|
||||
/* Other overall effect parameters */
|
||||
/*22*/ AWE_FX_INIT_PITCH, /* SHORT: pitch offset */
|
||||
/*23*/ AWE_FX_CHORUS, /* BYTE: chorus effects send (0-255) */
|
||||
/*24*/ AWE_FX_REVERB, /* BYTE: reverb effects send (0-255) */
|
||||
/*25*/ AWE_FX_CUTOFF, /* BYTE: up IFATN */
|
||||
/*26*/ AWE_FX_FILTERQ, /* BYTE: up CCCA */
|
||||
|
||||
/* Sample / loop offset changes */
|
||||
/*27*/ AWE_FX_SAMPLE_START, /* SHORT: offset */
|
||||
/*28*/ AWE_FX_LOOP_START, /* SHORT: offset */
|
||||
/*29*/ AWE_FX_LOOP_END, /* SHORT: offset */
|
||||
/*30*/ AWE_FX_COARSE_SAMPLE_START, /* SHORT: upper word offset */
|
||||
/*31*/ AWE_FX_COARSE_LOOP_START, /* SHORT: upper word offset */
|
||||
/*32*/ AWE_FX_COARSE_LOOP_END, /* SHORT: upper word offset */
|
||||
/*33*/ AWE_FX_ATTEN, /* BYTE: lo IFATN */
|
||||
|
||||
AWE_FX_END,
|
||||
};
|
||||
|
||||
#endif /* AWE_VOICE_H */
|
||||
390
project/jni/sdl_mixer/native_midi_gpl/emumidi.c
Normal file
390
project/jni/sdl_mixer/native_midi_gpl/emumidi.c
Normal file
@@ -0,0 +1,390 @@
|
||||
/************************************************************************
|
||||
emumidi.c -- emulation of midi device for FM/OPL3/GUS
|
||||
|
||||
Copyright (C) 1994-1996 Nathan I. Laredo
|
||||
|
||||
This program is modifiable/redistributable under the terms
|
||||
of the GNU General Public Licence.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
Send your comments and all your spare pocket change to
|
||||
laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
|
||||
Kelly Drive, Lackland AFB, TX 78236-5128, USA.
|
||||
*************************************************************************/
|
||||
/* edited by Peter Kutak */
|
||||
/* email : kutak@stonline.sk */
|
||||
|
||||
#if defined(linux) || defined(__FreeBSD__)
|
||||
|
||||
#include "emumidi.h"
|
||||
|
||||
SEQ_USE_EXTBUF();
|
||||
|
||||
extern int seqfd, play_ext, play_gus, play_fm, play_awe;
|
||||
extern int gus_dev, sb_dev, ext_dev, awe_dev;
|
||||
extern struct synth_info card_info[MAX_CARDS];
|
||||
extern int chanmask, perc, ticks, dochan, wantopl3, MT32;
|
||||
extern int patchloaded[256], fmloaded[256], useprog[16];
|
||||
int note_vel[16][128];
|
||||
struct voicestate voice[2][36];
|
||||
struct chanstate channel[16];
|
||||
#define C_GUS 0
|
||||
#define C_FM 1
|
||||
#define CN (ISGUS(chn) ? C_GUS : C_FM)
|
||||
#define CHANNEL (dochan ? chn : 0)
|
||||
|
||||
void load_sysex(length, data, type)
|
||||
int length;
|
||||
unsigned char *data;
|
||||
int type;
|
||||
{
|
||||
unsigned long int i, j;
|
||||
|
||||
/*
|
||||
* If the system exclusive is for roland, evaluate it. More than
|
||||
* roland could be evaluated here if i had documentation. Please
|
||||
* submit patches for any other hardware to laredo@gnu.ai.mit.edu
|
||||
* Complete emulation of all GS sysex messages in the works....
|
||||
*/
|
||||
if (length > 7 && data[0] == 0x41 && data[2] == 0x42 && data[3] == 0x12) {
|
||||
/* GS DATA SET MESSAGES */
|
||||
if (data[4] == 0x40 && (data[5] & 0xf0) == 0x10 && data[6] == 0x15) {
|
||||
/* USE RHYTHM PART */
|
||||
if (!(i = (data[5] & 0xf)))
|
||||
i = 0x09;
|
||||
else if (i < 10)
|
||||
i--;
|
||||
i = 1<<i;
|
||||
if (data[7])
|
||||
perc |= i;
|
||||
else
|
||||
perc &= ~i;
|
||||
}
|
||||
if ((data[4] == 0x40 || data[4] == 0) &&
|
||||
data[5] == 0x00 && data[6] == 0x7f) { /* GS RESET */
|
||||
perc = 0x0200; /* percussion in channel 10 only */
|
||||
for (i = 0; i < 16; i++) { /* set state info */
|
||||
for (j = 0; j < 128; j++)
|
||||
note_vel[i][j] = 0;
|
||||
channel[i].bender = channel[i].oldbend = 8192;
|
||||
channel[i].bender_range = channel[i].oldrange = 2;
|
||||
channel[i].controller[CTL_PAN] = 64;
|
||||
channel[i].controller[CTL_SUSTAIN] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!play_ext)
|
||||
return;
|
||||
if (type == MIDI_SYSTEM_PREFIX)
|
||||
SEQ_MIDIOUT(ext_dev, MIDI_SYSTEM_PREFIX);
|
||||
for (i = 0; i < length; i++)
|
||||
SEQ_MIDIOUT(ext_dev, data[i]);
|
||||
}
|
||||
|
||||
int seq_set_patch(chn, pgm)
|
||||
int chn, pgm;
|
||||
{
|
||||
if (MT32 && pgm < 128)
|
||||
pgm = mt32pgm[pgm];
|
||||
if (useprog[chn])
|
||||
pgm = useprog[chn] - 1;
|
||||
if (ISMIDI(chn)) {
|
||||
SEQ_MIDIOUT(ext_dev, MIDI_PGM_CHANGE + CHANNEL);
|
||||
SEQ_MIDIOUT(ext_dev, pgm);
|
||||
} else if (ISAWE(chn)) {
|
||||
SEQ_SET_PATCH(awe_dev, chn, pgm);
|
||||
} else if (ISPERC(chn)) {
|
||||
if (ISGUS(chn) && patchloaded[pgm] != 1)
|
||||
return -1;
|
||||
else if (ISFM(chn) && !fmloaded[pgm])
|
||||
return -1;
|
||||
} else if (ISGUS(chn) && patchloaded[pgm] != 1)
|
||||
/* find first loaded gus program to replace missing one */
|
||||
for (pgm = 0; patchloaded[pgm] != 1; pgm++);
|
||||
return (channel[chn].program = pgm);
|
||||
}
|
||||
|
||||
/* finetune returns exact frequency with bender applied. Not used */
|
||||
/*
|
||||
int finetune(chn, note)
|
||||
int chn, note;
|
||||
{
|
||||
long int r, b, d;
|
||||
|
||||
r = channel[chn].bender_range;
|
||||
b = channel[chn].bender - 8192;
|
||||
if (!b || r + note > 127 || r - note < 0)
|
||||
return n_freq[note];
|
||||
r = n_freq[note + r] - n_freq[note - r];
|
||||
d = b * r;
|
||||
d /= 8192;
|
||||
return n_freq[note] + d;
|
||||
|
||||
}
|
||||
*/
|
||||
extern int _seqbufptr;
|
||||
|
||||
void seq_stop_note(dev, chn, note, vel)
|
||||
int dev, chn, note, vel;
|
||||
{
|
||||
int i, card = CN;
|
||||
|
||||
note_vel[chn][note] = 0;
|
||||
if (ISMIDI(chn)) {
|
||||
SEQ_MIDIOUT(dev, MIDI_NOTEOFF + CHANNEL);
|
||||
SEQ_MIDIOUT(dev, note);
|
||||
SEQ_MIDIOUT(dev, vel);
|
||||
} else if (ISAWE(chn)) {
|
||||
SEQ_STOP_NOTE(dev, chn, note, vel);
|
||||
} else
|
||||
for (i = 0; i < card_info[dev].nr_voices; i++)
|
||||
if (voice[card][i].channel == chn &&
|
||||
voice[card][i].note == note) {
|
||||
voice[card][i].dead = 1;
|
||||
voice[card][i].timestamp /= 2;
|
||||
if (!channel[chn].controller[CTL_SUSTAIN] && !ISPERC(chn))
|
||||
SEQ_STOP_NOTE(dev, i, note, vel);
|
||||
}
|
||||
}
|
||||
|
||||
void seq_key_pressure(dev, chn, note, vel)
|
||||
int dev, chn, note, vel;
|
||||
{
|
||||
int i, card = CN;
|
||||
|
||||
if (ISMIDI(chn)) {
|
||||
SEQ_MIDIOUT(dev, MIDI_KEY_PRESSURE + CHANNEL);
|
||||
SEQ_MIDIOUT(dev, note);
|
||||
SEQ_MIDIOUT(dev, vel);
|
||||
} else if (ISAWE(chn)) {
|
||||
AWE_KEY_PRESSURE(dev, chn, note, vel);
|
||||
} else
|
||||
for (i = 0; i < card_info[dev].nr_voices; i++)
|
||||
if (voice[card][i].channel == chn &&
|
||||
voice[card][i].note == note)
|
||||
SEQ_KEY_PRESSURE(dev, i, note, vel);
|
||||
}
|
||||
|
||||
int new_voice(dev, chn)
|
||||
int dev, chn;
|
||||
{
|
||||
int i, oldest, last, card = CN;
|
||||
|
||||
if (ISFM(chn) && fmloaded[channel[chn].program] == OPL3_PATCH)
|
||||
last = 6; /* 4-op voice can only use first six voices */
|
||||
else
|
||||
last = card_info[dev].nr_voices;
|
||||
|
||||
for (i = oldest = 0; i < last; i++)
|
||||
if (voice[card][i].timestamp < voice[card][oldest].timestamp)
|
||||
oldest = i;
|
||||
return oldest;
|
||||
}
|
||||
|
||||
void seq_start_note(dev, chn, note, vel)
|
||||
int dev, chn, note, vel;
|
||||
{
|
||||
int v, c, card = CN;
|
||||
|
||||
note_vel[chn][note] = vel;
|
||||
if (ISMIDI(chn)) {
|
||||
SEQ_MIDIOUT(dev, MIDI_NOTEON + CHANNEL);
|
||||
SEQ_MIDIOUT(dev, note);
|
||||
SEQ_MIDIOUT(dev, vel);
|
||||
} else if (vel == 0)
|
||||
seq_stop_note(dev, chn, note, 64);
|
||||
else if (ISAWE(chn)) {
|
||||
SEQ_START_NOTE(dev, chn, note, vel);
|
||||
} else {
|
||||
v = new_voice(dev, chn);
|
||||
SEQ_SET_PATCH(dev, v, channel[chn].program);
|
||||
SEQ_BENDER_RANGE(dev, v, (channel[chn].bender_range * 100));
|
||||
SEQ_BENDER(dev, v, channel[chn].bender);
|
||||
SEQ_CONTROL(dev, v, CTL_PAN,
|
||||
channel[chn].controller[CTL_PAN]);
|
||||
SEQ_START_NOTE(dev, v, note, vel);
|
||||
voice[card][v].note = note;
|
||||
voice[card][v].channel = chn;
|
||||
voice[card][v].timestamp = ticks;
|
||||
voice[card][v].dead = 0;
|
||||
if ((c = channel[chn].controller[CTL_CHORUS_DEPTH] * 8)) {
|
||||
if (channel[chn].bender_range)
|
||||
c /= channel[chn].bender_range;
|
||||
v = new_voice(dev, chn);
|
||||
SEQ_SET_PATCH(dev, v, channel[chn].program);
|
||||
SEQ_BENDER_RANGE(dev, v, (channel[chn].bender_range * 100));
|
||||
if (channel[chn].bender + c < 0x4000) {
|
||||
SEQ_BENDER(dev, v, channel[chn].bender + c);
|
||||
} else {
|
||||
SEQ_BENDER(dev, v, channel[chn].bender - c);
|
||||
}
|
||||
/* put chorus note on the "extreme" side */
|
||||
c = channel[chn].controller[CTL_PAN];
|
||||
if (c < 64)
|
||||
c = 0;
|
||||
else if (c > 64)
|
||||
c = 127;
|
||||
SEQ_CONTROL(dev, v, CTL_PAN, c);
|
||||
SEQ_START_NOTE(dev, v, note, vel);
|
||||
voice[card][v].note = note;
|
||||
voice[card][v].channel = chn;
|
||||
/* allow chorus note to be stolen very quickly */
|
||||
voice[card][v].timestamp = ticks / 2;
|
||||
voice[card][v].dead = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int rpn1[16] =
|
||||
{127, 127, 127, 127, 127, 127, 127, 127,
|
||||
127, 127, 127, 127, 127, 127, 127, 127};
|
||||
static int rpn2[16] =
|
||||
{127, 127, 127, 127, 127, 127, 127, 127,
|
||||
127, 127, 127, 127, 127, 127, 127, 127};
|
||||
|
||||
void seq_control(dev, chn, p1, p2)
|
||||
int dev, chn, p1, p2;
|
||||
{
|
||||
int i, card = CN;
|
||||
|
||||
channel[chn].controller[p1] = p2;
|
||||
|
||||
if (ISMIDI(chn)) {
|
||||
SEQ_MIDIOUT(dev, MIDI_CTL_CHANGE + CHANNEL);
|
||||
SEQ_MIDIOUT(dev, p1);
|
||||
SEQ_MIDIOUT(dev, p2);
|
||||
}
|
||||
if (p1 == 7 || p1 == 39)
|
||||
return;
|
||||
switch (p1) {
|
||||
case CTL_SUSTAIN:
|
||||
if (ISAWE(chn)) {
|
||||
SEQ_CONTROL(dev, chn, p1, p2);
|
||||
} else if (!ISMIDI(chn))
|
||||
if (p1 == CTL_SUSTAIN && !p2) {
|
||||
for (i = 0; i < card_info[card].nr_voices; i++)
|
||||
if (voice[card][i].channel == chn
|
||||
&& voice[card][i].dead) {
|
||||
SEQ_STOP_NOTE(dev, i, voice[card][i].note, 64);
|
||||
voice[card][i].dead = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CTL_REGIST_PARM_NUM_MSB:
|
||||
rpn1[chn] = p2;
|
||||
break;
|
||||
case CTL_REGIST_PARM_NUM_LSB:
|
||||
rpn2[chn] = p2;
|
||||
break;
|
||||
case CTL_DATA_ENTRY:
|
||||
if (rpn1[chn] == 0 && rpn2[chn] == 0) {
|
||||
channel[chn].oldrange = channel[chn].bender_range;
|
||||
channel[chn].bender_range = p2;
|
||||
rpn1[chn] = rpn2[chn] = 127;
|
||||
if (ISAWE(chn)) {
|
||||
SEQ_BENDER_RANGE(dev, chn, p2 * 100);
|
||||
} else if (!ISMIDI(chn))
|
||||
for (i = 0; i < card_info[card].nr_voices; i++)
|
||||
SEQ_BENDER_RANGE(dev, i, p2 * 100);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* sent on the off chance the sound driver is enhanced */
|
||||
if (ISAWE(chn)) {
|
||||
SEQ_CONTROL(dev, chn, p1, p2);
|
||||
} else if (!ISMIDI(chn) && (p1 < 0x10 || (p1 & 0xf0) == 0x50))
|
||||
for (i = 0; i < card_info[card].nr_voices; i++)
|
||||
if (voice[card][i].channel == chn)
|
||||
SEQ_CONTROL(dev, i, p1, p2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void seq_chn_pressure(dev, chn, vel)
|
||||
int dev, chn, vel;
|
||||
{
|
||||
int card = CN, i;
|
||||
|
||||
channel[chn].pressure = vel;
|
||||
if (ISMIDI(chn)) {
|
||||
SEQ_MIDIOUT(dev, MIDI_CHN_PRESSURE + CHANNEL);
|
||||
SEQ_MIDIOUT(dev, vel);
|
||||
} else if (ISAWE(chn)) {
|
||||
AWE_CHN_PRESSURE(dev, chn, vel);
|
||||
} else
|
||||
for (i = 0; i < card_info[dev].nr_voices; i++)
|
||||
if (voice[card][i].channel == chn)
|
||||
SEQ_KEY_PRESSURE(dev, i, voice[card][i].note, vel);
|
||||
}
|
||||
|
||||
void seq_bender(dev, chn, p1, p2)
|
||||
int dev, chn, p1, p2;
|
||||
{
|
||||
int card = CN, i, val;
|
||||
|
||||
val = (p2 << 7) + p1;
|
||||
channel[chn].oldbend = channel[chn].bender;
|
||||
channel[chn].bender = val;
|
||||
|
||||
if (ISMIDI(chn)) {
|
||||
SEQ_MIDIOUT(dev, MIDI_PITCH_BEND + CHANNEL);
|
||||
SEQ_MIDIOUT(dev, p1);
|
||||
SEQ_MIDIOUT(dev, p2);
|
||||
} else if (ISAWE(chn)) {
|
||||
SEQ_BENDER(dev, chn, val);
|
||||
} else
|
||||
for (i = 0; i < card_info[dev].nr_voices; i++)
|
||||
if (voice[card][i].channel == chn)
|
||||
SEQ_BENDER(dev, i, val);
|
||||
}
|
||||
|
||||
void seq_reset()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
_seqbufptr = ticks = 0;
|
||||
ioctl(seqfd, SNDCTL_SEQ_RESET);
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (ISMIDI(i)) {
|
||||
seq_control(ext_dev,i,0,0);
|
||||
seq_control(ext_dev,i,32,0);
|
||||
}
|
||||
seq_set_patch(i, 0);
|
||||
for (j = 0; j < 128; j++)
|
||||
note_vel[i][j] = 0;
|
||||
channel[i].bender = channel[i].oldbend = 8192;
|
||||
channel[i].bender_range = channel[i].oldrange = 2;
|
||||
channel[i].controller[CTL_PAN] = 64;
|
||||
channel[i].controller[CTL_SUSTAIN] = 0;
|
||||
}
|
||||
if (play_gus)
|
||||
for (i = 0; i < card_info[gus_dev].nr_voices; i++) {
|
||||
SEQ_CONTROL(gus_dev, i, SEQ_VOLMODE, VOL_METHOD_LINEAR);
|
||||
if (voice[0][i].note)
|
||||
SEQ_STOP_NOTE(gus_dev, i, voice[0][i].note, 64);
|
||||
voice[0][i].dead = voice[0][i].timestamp = -1;
|
||||
}
|
||||
if (play_fm) {
|
||||
if (wantopl3)
|
||||
ioctl(seqfd, SNDCTL_FM_4OP_ENABLE, &sb_dev);
|
||||
for (i = 0; i < card_info[sb_dev].nr_voices; i++) {
|
||||
SEQ_CONTROL(sb_dev, i, SEQ_VOLMODE, VOL_METHOD_LINEAR);
|
||||
if (voice[1][i].note)
|
||||
SEQ_STOP_NOTE(sb_dev, i, voice[1][i].note, 64);
|
||||
voice[1][i].dead = voice[1][i].timestamp = -1;
|
||||
}
|
||||
}
|
||||
if (play_awe) {
|
||||
AWE_SET_CHANNEL_MODE(awe_dev, 1);
|
||||
AWE_DRUM_CHANNELS(awe_dev, perc);
|
||||
AWE_TERMINATE_ALL(awe_dev);
|
||||
for (i = 0; i < card_info[awe_dev].nr_voices; i++) {
|
||||
voice[0][i].dead = voice[0][i].timestamp = -1;
|
||||
}
|
||||
}
|
||||
SEQ_DUMPBUF();
|
||||
}
|
||||
|
||||
#endif /* linux || FreeBSD */
|
||||
63
project/jni/sdl_mixer/native_midi_gpl/emumidi.h
Normal file
63
project/jni/sdl_mixer/native_midi_gpl/emumidi.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/************************************************************************
|
||||
emumidi.h -- tables and includes required by emumidi.c
|
||||
|
||||
Copyright (C) 1994-1996 Nathan I. Laredo
|
||||
|
||||
This program is modifiable/redistributable under the terms
|
||||
of the GNU General Public Licence.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 2139, USA.
|
||||
Send your comments and all your spare pocket change to
|
||||
laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
|
||||
Kelly Drive, Lackland AFB, TX 78236-5128, USA.
|
||||
*************************************************************************/
|
||||
#include "playmidi.h"
|
||||
#ifdef linux
|
||||
#include <linux/ultrasound.h>
|
||||
#else
|
||||
#include <machine/ultrasound.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TABLE OF NEARLY EXACT FREQUENCIES FOR ALL MIDI NOTES (A=440Hz)
|
||||
* the whole table is really not necessary, but it prevents some
|
||||
* rounding errors by having it complete, and the cost of 128
|
||||
* integers is cheaper than the cpu cost of multiple right shifts
|
||||
* of a table of twelve frequencies, and definately cheaper than
|
||||
* calculating freq = 13.75 * 2^((n + 4)/12) for each note value,
|
||||
* which is how this table was created.
|
||||
*/
|
||||
|
||||
unsigned int n_freq[128] =
|
||||
{
|
||||
/* C C# D D# E F F# G G# A A# B */
|
||||
16, 17, 18, 19, 21, 22, 23, 24, 26, 28, 29, 31,
|
||||
33, 34, 37, 39, 41, 44, 46, 49, 52, 55, 58, 62,
|
||||
65, 69, 73, 78, 82, 87, 92, 98, 103, 110, 117, 123,
|
||||
131, 139, 147, 156, 165, 175, 185, 195, 207, 220, 233, 247,
|
||||
262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494,
|
||||
523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988,
|
||||
1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976,
|
||||
2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,
|
||||
4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902,
|
||||
8372, 8870, 9397, 9956,10548,11175,11840,12544,13290,14080,14917,15804,
|
||||
16744,17740,18795,19912,21096,22351,23680,25088
|
||||
};
|
||||
|
||||
/* MT-32 emulation translate table */
|
||||
int mt32pgm[128] =
|
||||
{
|
||||
0, 1, 2, 4, 4, 5, 5, 3, 16, 16, 16, 16, 19,
|
||||
19, 19, 21, 6, 6, 6, 7, 7, 7, 8, 8, 62, 57,
|
||||
63, 58, 38, 38, 39, 39, 88, 33, 52, 35, 97, 100, 38,
|
||||
39, 14, 102, 68, 103, 44, 92, 46, 80, 48, 49, 51, 45,
|
||||
40, 40, 42, 42, 43, 46, 46, 24, 25, 28, 27, 104, 32,
|
||||
32, 34, 33, 36, 37, 39, 35, 79, 73, 76, 72, 74, 75,
|
||||
64, 65, 66, 67, 71, 71, 69, 70, 60, 22, 56, 59, 57,
|
||||
63, 60, 60, 58, 61, 61, 11, 11, 99, 100, 9, 14, 13,
|
||||
12, 107, 106, 77, 78, 78, 76, 111, 47, 117, 127, 115, 118,
|
||||
116, 118, 126, 121, 121, 55, 124, 120, 125, 126, 127
|
||||
};
|
||||
|
||||
106
project/jni/sdl_mixer/native_midi_gpl/gmvoices.h
Normal file
106
project/jni/sdl_mixer/native_midi_gpl/gmvoices.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/********************************************************************
|
||||
gmvoices.h -- List of GM voice filenames for GUS.
|
||||
|
||||
Copyright (C) 1994-1996 Nathan I. Laredo
|
||||
|
||||
This program is modifiable/redistributable under the terms
|
||||
of the GNU General Public Licence.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
Send your comments and all your spare pocket change to
|
||||
laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
|
||||
Kelly Drive, Lackland AFB, TX 78236-5128, USA.
|
||||
|
||||
********************************************************************/
|
||||
char *gmvoice[256] = {
|
||||
/* [Melodic Patches] */
|
||||
/* 000 */ "acpiano", /* 001 */ "britepno", /* 002 */ "synpiano",
|
||||
/* 003 */ "honky", /* 004 */ "epiano1", /* 005 */ "epiano2",
|
||||
/* 006 */ "hrpschrd", /* 007 */ "clavinet", /* 008 */ "celeste",
|
||||
/* 009 */ "glocken", /* 010 */ "musicbox", /* 011 */ "vibes",
|
||||
/* 012 */ "marimba", /* 013 */ "xylophon", /* 014 */ "tubebell",
|
||||
/* 015 */ "santur", /* 016 */ "homeorg", /* 017 */ "percorg",
|
||||
/* 018 */ "rockorg", /* 019 */ "church", /* 020 */ "reedorg",
|
||||
/* 021 */ "accordn", /* 022 */ "harmonca", /* 023 */ "concrtna",
|
||||
/* 024 */ "nyguitar", /* 025 */ "acguitar", /* 026 */ "jazzgtr",
|
||||
/* 027 */ "cleangtr", /* 028 */ "mutegtr", /* 029 */ "odguitar",
|
||||
/* 030 */ "distgtr", /* 031 */ "gtrharm", /* 032 */ "acbass",
|
||||
/* 033 */ "fngrbass", /* 034 */ "pickbass", /* 035 */ "fretless",
|
||||
/* 036 */ "slapbas1", /* 037 */ "slapbas2", /* 038 */ "synbass1",
|
||||
/* 039 */ "synbass2", /* 040 */ "violin", /* 041 */ "viola",
|
||||
/* 042 */ "cello", /* 043 */ "contraba", /* 044 */ "marcato",
|
||||
/* 045 */ "pizzcato", /* 046 */ "harp", /* 047 */ "timpani",
|
||||
/* 048 */ "marcato", /* 049 */ "slowstr", /* 050 */ "synstr1",
|
||||
/* 051 */ "synstr2", /* 052 */ "choir", /* 053 */ "doo",
|
||||
/* 054 */ "voices", /* 055 */ "orchhit", /* 056 */ "trumpet",
|
||||
/* 057 */ "trombone", /* 058 */ "tuba", /* 059 */ "mutetrum",
|
||||
/* 060 */ "frenchrn", /* 061 */ "hitbrass", /* 062 */ "synbras1",
|
||||
/* 063 */ "synbras2", /* 064 */ "sprnosax", /* 065 */ "altosax",
|
||||
/* 066 */ "tenorsax", /* 067 */ "barisax", /* 068 */ "oboe",
|
||||
/* 069 */ "englhorn", /* 070 */ "bassoon", /* 071 */ "clarinet",
|
||||
/* 072 */ "piccolo", /* 073 */ "flute", /* 074 */ "recorder",
|
||||
/* 075 */ "woodflut", /* 076 */ "bottle", /* 077 */ "shakazul",
|
||||
/* 078 */ "whistle", /* 079 */ "ocarina", /* 080 */ "sqrwave",
|
||||
/* 081 */ "sawwave", /* 082 */ "calliope", /* 083 */ "chiflead",
|
||||
/* 084 */ "charang", /* 085 */ "voxlead", /* 086 */ "lead5th",
|
||||
/* 087 */ "basslead", /* 088 */ "fantasia", /* 089 */ "warmpad",
|
||||
/* 090 */ "polysyn", /* 091 */ "ghostie", /* 092 */ "bowglass",
|
||||
/* 093 */ "metalpad", /* 094 */ "halopad", /* 095 */ "sweeper",
|
||||
/* 096 */ "aurora", /* 097 */ "soundtrk", /* 098 */ "crystal",
|
||||
/* 099 */ "atmosphr", /* 100 */ "freshair", /* 101 */ "unicorn",
|
||||
/* 102 */ "sweeper", /* 103 */ "startrak", /* 104 */ "sitar",
|
||||
/* 105 */ "banjo", /* 106 */ "shamisen", /* 107 */ "koto",
|
||||
/* 108 */ "kalimba", /* 109 */ "bagpipes", /* 110 */ "fiddle",
|
||||
/* 111 */ "shannai", /* 112 */ "carillon", /* 113 */ "agogo",
|
||||
/* 114 */ "steeldrm", /* 115 */ "woodblk", /* 116 */ "taiko",
|
||||
/* 117 */ "toms", /* 118 */ "syntom", /* 119 */ "revcym",
|
||||
/* 120 */ "fx-fret", /* 121 */ "fx-blow", /* 122 */ "seashore",
|
||||
/* 123 */ "jungle", /* 124 */ "telephon", /* 125 */ "helicptr",
|
||||
/* 126 */ "applause", /* 127 */ "ringwhsl",
|
||||
/* [Drum Patches] */
|
||||
/* C 0 */ NULL, /* C#0 */ NULL, /* D 0 */ NULL,
|
||||
/* D#0 */ NULL, /* E 0 */ NULL, /* F 0 */ NULL,
|
||||
/* F#0 */ NULL, /* G 0 */ NULL, /* G#0 */ NULL,
|
||||
/* A 0 */ NULL, /* A#0 */ NULL, /* B 0 */ NULL,
|
||||
/* C 1 */ NULL, /* C#1 */ NULL, /* D 1 */ NULL,
|
||||
/* D#1 */ NULL, /* E 1 */ NULL, /* F 1 */ NULL,
|
||||
/* F#1 */ NULL, /* G 1 */ NULL, /* G#1 */ NULL,
|
||||
/* A 1 */ NULL, /* A#1 */ NULL, /* B 1 */ NULL,
|
||||
/* C 2 */ NULL, /* C#2 */ NULL, /* D 2 */ NULL,
|
||||
/* D#2 */ "highq", /* E 2 */ "slap", /* F 2 */ "scratch1",
|
||||
/* F#2 */ "scratch2", /* G 2 */ "sticks", /* G#2 */ "sqrclick",
|
||||
/* A 2 */ "metclick", /* A#2 */ "metbell", /* B 2 */ "kick1",
|
||||
/* C 3 */ "kick2", /* C#3 */ "stickrim", /* D 3 */ "snare1",
|
||||
/* D#3 */ "claps", /* E 3 */ "snare2", /* F 3 */ "tomlo2",
|
||||
/* F#3 */ "hihatcl", /* G 3 */ "tomlo1", /* G#3 */ "hihatpd",
|
||||
/* A 3 */ "tommid2", /* A#3 */ "hihatop", /* B 3 */ "tommid1",
|
||||
/* C 4 */ "tomhi2", /* C#4 */ "cymcrsh1", /* D 4 */ "tomhi1",
|
||||
/* D#4 */ "cymride1", /* E 4 */ "cymchina", /* F 4 */ "cymbell",
|
||||
/* F#4 */ "tamborin", /* G 4 */ "cymsplsh", /* G#4 */ "cowbell",
|
||||
/* A 4 */ "cymcrsh2", /* A#4 */ "vibslap", /* B 4 */ "cymride2",
|
||||
/* C 5 */ "bongohi", /* C#5 */ "bongolo", /* D 5 */ "congahi1",
|
||||
/* D#5 */ "congahi2", /* E 5 */ "congalo", /* F 5 */ "timbaleh",
|
||||
/* F#5 */ "timbalel", /* G 5 */ "agogohi", /* G#5 */ "agogolo",
|
||||
/* A 5 */ "cabasa", /* A#5 */ "maracas", /* B 5 */ "whistle1",
|
||||
/* C 6 */ "whistle2", /* C#6 */ "guiro1", /* D 6 */ "guiro2",
|
||||
/* D#6 */ "clave", /* E 6 */ "woodblk1", /* F 6 */ "woodblk2",
|
||||
/* F#6 */ "cuica1", /* G 6 */ "cuica2", /* G#6 */ "triangl1",
|
||||
/* A 6 */ "triangl2", /* A#6 */ "shaker", /* B 6 */ "jingles",
|
||||
/* C 7 */ "belltree", /* C#7 */ "castinet", /* D 7 */ "surdo1",
|
||||
/* D#7 */ "surdo2", /* E 7 */ NULL, /* F 7 */ NULL,
|
||||
/* F#7 */ NULL, /* G 7 */ NULL, /* G#7 */ NULL,
|
||||
/* A 7 */ NULL, /* A#7 */ NULL, /* B 7 */ NULL,
|
||||
/* C 8 */ NULL, /* C#8 */ NULL, /* D 8 */ NULL,
|
||||
/* D#8 */ NULL, /* E 8 */ NULL, /* F 8 */ NULL,
|
||||
/* F#8 */ NULL, /* G 8 */ NULL, /* G#8 */ NULL,
|
||||
/* A 8 */ NULL, /* A#8 */ NULL, /* B 8 */ NULL,
|
||||
/* C 9 */ NULL, /* C#9 */ NULL, /* D 9 */ NULL,
|
||||
/* D#9 */ NULL, /* E 9 */ NULL, /* F 9 */ NULL,
|
||||
/* F#9 */ NULL, /* G 9 */ NULL, /* G#9 */ NULL,
|
||||
/* A 9 */ NULL, /* A#9 */ NULL, /* B 9 */ NULL,
|
||||
/* C 10*/ NULL, /* C#10*/ NULL, /* D 10*/ NULL,
|
||||
/* D#10*/ NULL, /* E 10*/ NULL, /* F 10*/ NULL,
|
||||
/* F#10*/ NULL, /* G 10*/ NULL
|
||||
};
|
||||
39
project/jni/sdl_mixer/native_midi_gpl/gsvoices.h
Normal file
39
project/jni/sdl_mixer/native_midi_gpl/gsvoices.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**************************************************************
|
||||
* gsvoices.h - list of gs voice names - all 654 of SC88 *
|
||||
**************************************************************/
|
||||
#ifndef GSVOICES_H
|
||||
#define GSVOICES_H
|
||||
char *gsvoice[128] = {
|
||||
"Piano 1 ", "Piano 2 ", "Piano 3 ", "Honky-tonk ",
|
||||
"E.Piano 1 ", "E.Piano 2 ", "Harpsichord ", "Clav. ",
|
||||
"Celesta ", "Glockenspl ", "Music Box ", "Vibraphone ",
|
||||
"Marimba ", "Xylophone ", "Tubularbell ", "Santur ",
|
||||
"Organ 1 ", "Organ 2 ", "Organ 3 ", "Church Org1 ",
|
||||
"Reed Organ ", "Accordion F ", "Harmonica ", "Bandoneon ",
|
||||
"Nylon Gt. ", "Steel Gt. ", "Jazz Gt. ", "Clean Gt. ",
|
||||
"Muted Gt. ", "OverdriveGt ", "Dist.Gt. ", "Gt.Harmonix ",
|
||||
"Acoustic Bs ", "Fingered Bs ", "Picked Bass ", "Fretless Bs ",
|
||||
"Slap Bass 1 ", "Slap Bass 2 ", "Syn.Bass 1 ", "Syn.Bass 2 ",
|
||||
"Violin ", "Viola ", "Cello ", "Contrabass ",
|
||||
"Tremolo Str ", "Pizzicato ", "Harp ", "Timpani ",
|
||||
"Strings ", "SlowStrings ", "SynStrings1 ", "SynStrings2 ",
|
||||
"Choir Aahs ", "Voice Oohs ", "SynVox ", "Orchest.Hit ",
|
||||
"Trumpet ", "Trombone ", "Tuba ", "MuteTrumpet ",
|
||||
"French Horn ", "Brass 1 ", "Syn.Brass 1 ", "Syn.Brass 2 ",
|
||||
"Soprano Sax ", "Alto Sax ", "Tenor Sax ", "BaritoneSax ",
|
||||
"Oboe ", "EnglishHorn ", "Bassoon ", "Clarinet ",
|
||||
"Piccolo ", "Flute ", "Recorder ", "Pan Flute ",
|
||||
"Bottle Blow ", "Shakuhachi ", "Whistle ", "Ocarina ",
|
||||
"Square Wave ", "Saw Wave ", "SynCalliope ", "ChifferLead ",
|
||||
"Charang ", "Solo Vox ", "5th Saw ", "Bass & Lead ",
|
||||
"Fantasia ", "Warm Pad ", "Polysynth ", "Space Voice ",
|
||||
"Bowed Glass ", "Metal Pad ", "Halo Pad ", "Sweep Pad ",
|
||||
"Ice Rain ", "Soundtrack ", "Crystal ", "Atmosphere ",
|
||||
"Brightness ", "Goblin ", "Echo Drops ", "Star Theme ",
|
||||
"Sitar ", "Banjo ", "Shamisen ", "Koto ",
|
||||
"Kalimba ", "Bagpipe ", "Fiddle ", "Shanai ",
|
||||
"Tinkle Bell ", "Agogo ", "Steel Drums ", "Woodblock ",
|
||||
"Taiko ", "Melo. Tom 1 ", "Synth Drum ", "Reverse Cym ",
|
||||
"Gt.FretNoiz ", "BreathNoise ", "Seashore ", "Bird ",
|
||||
"Telephone 1 ", "Helicopter ", "Applause ", "Gun Shot " };
|
||||
#endif
|
||||
512
project/jni/sdl_mixer/native_midi_gpl/native_midi_gpl.c
Normal file
512
project/jni/sdl_mixer/native_midi_gpl/native_midi_gpl.c
Normal file
@@ -0,0 +1,512 @@
|
||||
/***************************************************************************
|
||||
native_midi_lnx.c
|
||||
-----------------
|
||||
|
||||
copyright : (C) 2002 by Peter Kuȇk
|
||||
email : kutak@stonline.sk
|
||||
***************************************************************************/
|
||||
|
||||
/* in this file is used code from PlayMidi Copyright (C) 1994-1996 Nathan I. Laredo */
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#if defined(linux) || defined(__FreeBSD__)
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include "SDL_thread.h"
|
||||
#include "native_midi.h"
|
||||
#include "playmidi.h"
|
||||
|
||||
SEQ_DEFINEBUF(SEQUENCERBLOCKSIZE);
|
||||
|
||||
int play_fm = 0, play_gus = 0, play_ext = 0, play_awe = 0;
|
||||
int opl3_patch_aviable = 0, fm_patch_aviable = 0;
|
||||
|
||||
struct miditrack seq[MAXTRKS];
|
||||
struct synth_info card_info[MAX_CARDS];
|
||||
|
||||
int FORCE_EXT_DEV = -1;
|
||||
int chanmask = 0xffff, perc = PERCUSSION;
|
||||
int dochan = 1, force8bit = 0, wantopl3 = FM_DEFAULT_MODE;
|
||||
int patchloaded[256], fmloaded[256], useprog[16], usevol[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
int reverb = 0, chorus = 0, nrsynths, nrmidis;
|
||||
int sb_dev = -1, gus_dev = -1, ext_dev = -1, awe_dev = -1, p_remap = 0;
|
||||
int seqfd, MT32 = 0;
|
||||
FILE *mfd;
|
||||
unsigned long int default_tempo;
|
||||
float skew = 1.0;
|
||||
char ImPlaying = 0;
|
||||
SDL_Thread *playevents_thread=NULL;
|
||||
|
||||
extern int ntrks;
|
||||
extern char *gmvoice[256];
|
||||
extern int mt32pgm[128];
|
||||
extern int note_vel[16][128];
|
||||
extern int playevents();
|
||||
extern int gus_load(int);
|
||||
extern int readmidi(unsigned char *, off_t);
|
||||
extern void loadfm();
|
||||
|
||||
void seqbuf_dump();
|
||||
int synth_setup();
|
||||
|
||||
struct _NativeMidiSong
|
||||
{
|
||||
char *filebuf;
|
||||
unsigned long int file_size;
|
||||
};
|
||||
|
||||
int native_midi_detect()
|
||||
{
|
||||
|
||||
int sbfd;
|
||||
int ret=0;
|
||||
|
||||
/* Open sequencer device */
|
||||
if ((seqfd = open(SEQUENCER_DEV, O_WRONLY, 0)) < 0)
|
||||
{
|
||||
perror("open " SEQUENCER_DEV);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gus_dev = -1;
|
||||
sb_dev = -1;
|
||||
ext_dev = -1;
|
||||
awe_dev = -1;
|
||||
play_fm = 0;
|
||||
play_gus = 0;
|
||||
play_ext = 0;
|
||||
play_awe = 0;
|
||||
|
||||
opl3_patch_aviable = 0;
|
||||
fm_patch_aviable = 0;
|
||||
|
||||
sbfd = open(SBMELODIC, O_RDONLY, 0);
|
||||
if (sbfd != -1)
|
||||
{
|
||||
close(sbfd);
|
||||
sbfd = open(SBDRUMS, O_RDONLY, 0);
|
||||
if (sbfd != -1)
|
||||
{
|
||||
close(sbfd);
|
||||
fm_patch_aviable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sbfd = open(O3MELODIC, O_RDONLY, 0);
|
||||
if (sbfd != -1)
|
||||
{
|
||||
close(sbfd);
|
||||
sbfd = open(O3DRUMS, O_RDONLY, 0);
|
||||
if (sbfd != -1)
|
||||
{
|
||||
close(sbfd);
|
||||
opl3_patch_aviable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ret=synth_setup();
|
||||
|
||||
/* Close sequencer device */
|
||||
close(seqfd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
NativeMidiSong *native_midi_loadsong(const char *midifile)
|
||||
{
|
||||
NativeMidiSong *song = NULL;
|
||||
char *extra;
|
||||
int piped = 0;
|
||||
struct stat info;
|
||||
|
||||
song = malloc(sizeof(NativeMidiSong));
|
||||
if (!song)
|
||||
{
|
||||
return NULL;
|
||||
};
|
||||
if (stat(midifile, &info) == -1)
|
||||
{
|
||||
if ((extra = malloc(strlen(midifile) + 4)) == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
sprintf(extra, "%s.mid", midifile);
|
||||
if (stat(extra, &info) == -1)
|
||||
{
|
||||
free(extra);
|
||||
goto end;
|
||||
}
|
||||
if ((mfd = fopen(extra, "r")) == NULL)
|
||||
{
|
||||
free(extra);
|
||||
goto end;
|
||||
}
|
||||
free(extra);
|
||||
} else
|
||||
{
|
||||
char *ext = strrchr(midifile, '.');
|
||||
if (ext && strcmp(ext, ".gz") == 0)
|
||||
{
|
||||
char temp[1024];
|
||||
piped = 1;
|
||||
sprintf(temp, "gzip -l %s", midifile);
|
||||
if ((mfd = popen(temp, "r")) == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
fgets(temp, sizeof(temp), mfd); /* skip 1st line */
|
||||
fgets(temp, sizeof(temp), mfd);
|
||||
strtok(temp, " "); /* compressed size */
|
||||
info.st_size = atoi(strtok(NULL, " ")); /* original size */
|
||||
pclose(mfd);
|
||||
sprintf(temp, "gzip -d -c %s",midifile);
|
||||
if ((mfd = popen(temp, "r")) == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
}else if ((mfd = fopen(midifile, "r")) == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if ((song->filebuf = malloc(info.st_size)) == NULL)
|
||||
{
|
||||
if (piped)
|
||||
{
|
||||
pclose(mfd);
|
||||
}else
|
||||
{
|
||||
fclose(mfd);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
song->file_size=info.st_size;
|
||||
fread(song->filebuf, 1, info.st_size, mfd);
|
||||
if (piped)
|
||||
{
|
||||
pclose(mfd);
|
||||
} else
|
||||
{
|
||||
fclose(mfd);
|
||||
}
|
||||
|
||||
return song;
|
||||
|
||||
end:
|
||||
free(song);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw)
|
||||
{
|
||||
NativeMidiSong *song = NULL;
|
||||
char *extra;
|
||||
|
||||
song = malloc(sizeof(NativeMidiSong));
|
||||
if (!song) {
|
||||
return NULL;
|
||||
};
|
||||
|
||||
SDL_RWseek(rw, 0, RW_SEEK_END);
|
||||
song->file_size = SDL_RWtell(rw);
|
||||
SDL_RWseek(rw, 0, RW_SEEK_SET);
|
||||
|
||||
song->filebuf = malloc(song->file_size);
|
||||
if (!song->filebuf) {
|
||||
free(song);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_RWread(rw, song->filebuf, song->file_size, 1);
|
||||
return song;
|
||||
}
|
||||
|
||||
void native_midi_freesong(NativeMidiSong *song)
|
||||
{
|
||||
free(song->filebuf);
|
||||
free(song);
|
||||
}
|
||||
|
||||
void native_midi_start(NativeMidiSong *song)
|
||||
{
|
||||
|
||||
int i, error = 0, j;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
useprog[i] = 0; /* reset options */
|
||||
}
|
||||
|
||||
/* Open sequencer device */
|
||||
if ((seqfd = open(SEQUENCER_DEV, O_WRONLY, 0)) < 0)
|
||||
{
|
||||
perror("open " SEQUENCER_DEV);
|
||||
goto eend;
|
||||
}
|
||||
if(!synth_setup()) { goto end;};
|
||||
|
||||
|
||||
if (play_gus)
|
||||
{
|
||||
gus_load(-1);
|
||||
}
|
||||
default_tempo = 500000;
|
||||
/* error holds number of tracks read */
|
||||
error = readmidi(song->filebuf, song->file_size);
|
||||
if (play_gus && error > 0)
|
||||
{
|
||||
int i; /* need to keep other i safe */
|
||||
#define CMD (seq[i].data[j] & 0xf0)
|
||||
#define CHN (seq[i].data[j] & 0x0f)
|
||||
#define PGM (seq[i].data[j + 1])
|
||||
/* REALLY STUPID way to preload GUS, but it works */
|
||||
for (i = 0; i < ntrks; i++)
|
||||
for (j = 0; j < seq[i].length - 5; j++)
|
||||
if (ISGUS(CHN) && !(PGM & 0x80) &&
|
||||
((CMD == MIDI_PGM_CHANGE && !ISPERC(CHN))
|
||||
|| (CMD == MIDI_NOTEON && ISPERC(CHN))))
|
||||
gus_load(ISPERC(CHN) ? PGM + 128 :
|
||||
useprog[CHN] ? useprog[CHN] - 1 :
|
||||
MT32 ? mt32pgm[PGM] : PGM);
|
||||
/* make sure that some program was loaded to use */
|
||||
for (j = 0; patchloaded[j] != 1 && j < 128; j++);
|
||||
if (j > 127)
|
||||
gus_load(0);
|
||||
}
|
||||
/* if there's an error skip to next file */
|
||||
if (error > 0) /* error holds number of tracks read */
|
||||
{
|
||||
ImPlaying=1;
|
||||
playevents_thread=SDL_CreateThread(playevents,NULL);
|
||||
}
|
||||
|
||||
end:
|
||||
eend:
|
||||
return;
|
||||
}
|
||||
|
||||
void native_midi_stop()
|
||||
{
|
||||
/* Close sequencer device */
|
||||
close(seqfd);
|
||||
}
|
||||
|
||||
int native_midi_active()
|
||||
{
|
||||
return ImPlaying;
|
||||
}
|
||||
|
||||
void native_midi_setvolume(int volume)
|
||||
{
|
||||
}
|
||||
|
||||
const char *native_midi_error(void)
|
||||
{
|
||||
return "stala sa chyba";
|
||||
}
|
||||
|
||||
void seqbuf_dump()
|
||||
{
|
||||
if (_seqbufptr)
|
||||
if (write(seqfd, _seqbuf, _seqbufptr) == -1) {
|
||||
perror("write " SEQUENCER_DEV);
|
||||
return;
|
||||
}
|
||||
_seqbufptr = 0;
|
||||
}
|
||||
|
||||
int synth_setup()
|
||||
{
|
||||
int i;
|
||||
char *nativemusicenv = getenv("SDL_NATIVE_MUSIC");
|
||||
char *extmidi=getenv("SDL_NATIVE_MUSIC_EXT");
|
||||
|
||||
if(extmidi)
|
||||
{
|
||||
|
||||
FORCE_EXT_DEV = atoi(extmidi);
|
||||
printf("EXT midi %s , %d \n",extmidi,FORCE_EXT_DEV);
|
||||
}
|
||||
|
||||
if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrsynths) == -1)
|
||||
{
|
||||
fprintf(stderr, "there is no soundcard\n");
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < nrsynths; i++)
|
||||
{
|
||||
card_info[i].device = i;
|
||||
if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info[i]) == -1)
|
||||
{
|
||||
fprintf(stderr, "cannot get info on soundcard\n");
|
||||
perror(SEQUENCER_DEV);
|
||||
return 0;
|
||||
}
|
||||
card_info[i].device = i;
|
||||
if (card_info[i].synth_type == SYNTH_TYPE_SAMPLE
|
||||
&& card_info[i].synth_subtype == SAMPLE_TYPE_GUS)
|
||||
{
|
||||
gus_dev = i;
|
||||
}else if (card_info[i].synth_type == SYNTH_TYPE_SAMPLE
|
||||
&& card_info[i].synth_subtype == SAMPLE_TYPE_AWE32)
|
||||
{
|
||||
awe_dev = i;
|
||||
}else if (card_info[i].synth_type == SYNTH_TYPE_FM)
|
||||
{
|
||||
sb_dev = i;
|
||||
if (play_fm)
|
||||
loadfm();
|
||||
if (wantopl3)
|
||||
{
|
||||
card_info[i].nr_voices = 12; /* we have 12 with 4-op */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gus_dev >= 0) {
|
||||
if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &gus_dev) == -1)
|
||||
{
|
||||
perror("Sample reset");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &nrmidis) == -1)
|
||||
{
|
||||
fprintf(stderr, "can't get info about midi ports\n");
|
||||
return 0;
|
||||
}
|
||||
if (nrmidis > 0) {
|
||||
if (FORCE_EXT_DEV >= 0)
|
||||
ext_dev = FORCE_EXT_DEV;
|
||||
else
|
||||
ext_dev = nrmidis - 1;
|
||||
}
|
||||
|
||||
if( nativemusicenv ) /* select device by SDL_NATIVE_MUSIC */
|
||||
{
|
||||
if(strcasecmp(nativemusicenv,"GUS") == 0)
|
||||
{
|
||||
if( gus_dev >= 0 )
|
||||
{
|
||||
play_gus = -1;
|
||||
awe_dev = -1;
|
||||
sb_dev = -1;
|
||||
ext_dev = -1;
|
||||
return 1;
|
||||
}else
|
||||
{
|
||||
play_gus = 0;
|
||||
return 0;
|
||||
}
|
||||
}else if(strcasecmp(nativemusicenv,"AWE") == 0)
|
||||
{
|
||||
if( awe_dev >= 0 )
|
||||
{
|
||||
play_awe = -1;
|
||||
gus_dev = -1;
|
||||
sb_dev = -1;
|
||||
ext_dev = -1;
|
||||
return 1;
|
||||
}else
|
||||
{
|
||||
play_awe = 0;
|
||||
return 0;
|
||||
}
|
||||
}else if(strcasecmp(nativemusicenv,"FM") == 0)
|
||||
{
|
||||
if( sb_dev >= 0 && fm_patch_aviable )
|
||||
{
|
||||
play_fm = -1;
|
||||
gus_dev = -1;
|
||||
awe_dev = -1;
|
||||
ext_dev = -1;
|
||||
wantopl3 = 0;
|
||||
return 1;
|
||||
}else
|
||||
{
|
||||
play_fm = 0;
|
||||
return 0;
|
||||
}
|
||||
}else if(strcasecmp(nativemusicenv,"OPL3") == 0)
|
||||
{
|
||||
if( sb_dev >= 0 && opl3_patch_aviable )
|
||||
{
|
||||
play_fm = -1;
|
||||
gus_dev = -1;
|
||||
awe_dev = -1;
|
||||
ext_dev = -1;
|
||||
wantopl3 = 1;
|
||||
return 1;
|
||||
}else
|
||||
{
|
||||
play_fm = 0;
|
||||
return 0;
|
||||
}
|
||||
}else if(strcasecmp(nativemusicenv,"EXT") == 0)
|
||||
{
|
||||
if( ext_dev >= 0 )
|
||||
{
|
||||
play_ext = -1;
|
||||
gus_dev = -1;
|
||||
awe_dev = -1;
|
||||
sb_dev = -1;
|
||||
return 1;
|
||||
}else
|
||||
{
|
||||
play_ext = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* autoselect best device */
|
||||
if( gus_dev >= 0 )
|
||||
{
|
||||
play_gus = -1;
|
||||
awe_dev = -1;
|
||||
sb_dev = -1;
|
||||
ext_dev = -1;
|
||||
return 1;
|
||||
}
|
||||
if( awe_dev >= 0 )
|
||||
{
|
||||
play_awe = -1;
|
||||
gus_dev = -1;
|
||||
sb_dev = -1;
|
||||
ext_dev = -1;
|
||||
return 1;
|
||||
}
|
||||
if( sb_dev >= 0 && fm_patch_aviable )
|
||||
{
|
||||
play_fm = -1;
|
||||
gus_dev = -1;
|
||||
awe_dev = -1;
|
||||
ext_dev = -1;
|
||||
return 2; /* return 1 if use FM befor Timidity */
|
||||
}
|
||||
if( ext_dev >= 0 )
|
||||
{
|
||||
play_ext = -1;
|
||||
gus_dev = -1;
|
||||
awe_dev = -1;
|
||||
sb_dev = -1;
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* linux || FreeBSD */
|
||||
412
project/jni/sdl_mixer/native_midi_gpl/patchload.c
Normal file
412
project/jni/sdl_mixer/native_midi_gpl/patchload.c
Normal file
@@ -0,0 +1,412 @@
|
||||
/************************************************************************
|
||||
patchload.c -- loads patches for playmidi package
|
||||
Some of this code was adapted from code written by Hannu Solovainen
|
||||
|
||||
Copyright (C) 1994-1996 Nathan I. Laredo
|
||||
|
||||
This program is modifiable/redistributable under the terms
|
||||
of the GNU General Public Licence.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
Send your comments and all your spare pocket change to
|
||||
laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
|
||||
Kelly Drive, Lackland AFB, TX 78236-5128, USA.
|
||||
*************************************************************************/
|
||||
/* edited by Peter Kutak */
|
||||
/* email : kutak@stonline.sk */
|
||||
|
||||
#if defined(linux) || defined(__FreeBSD__)
|
||||
|
||||
#include "playmidi.h"
|
||||
#ifdef linux
|
||||
#include <linux/ultrasound.h>
|
||||
#else
|
||||
#include <machine/ultrasound.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "gmvoices.h"
|
||||
|
||||
SEQ_USE_EXTBUF();
|
||||
extern int play_gus, play_sb, play_ext, playing, verbose, force8bit;
|
||||
extern int reverb, fmloaded[256], patchloaded[256];
|
||||
extern int gus_dev, sb_dev, ext_dev, seqfd, wantopl3;
|
||||
extern struct synth_info card_info[MAX_CARDS];
|
||||
|
||||
static int use8bit = 0;
|
||||
|
||||
struct pat_header {
|
||||
char magic[12];
|
||||
char version[10];
|
||||
char description[60];
|
||||
unsigned char instruments;
|
||||
char voices;
|
||||
char channels;
|
||||
unsigned short nr_waveforms;
|
||||
unsigned short master_volume;
|
||||
unsigned int data_size;
|
||||
};
|
||||
|
||||
struct sample_header {
|
||||
char name[7];
|
||||
unsigned char fractions;
|
||||
int len;
|
||||
int loop_start;
|
||||
int loop_end;
|
||||
unsigned short base_freq;
|
||||
int low_note;
|
||||
int high_note;
|
||||
int base_note;
|
||||
short detune;
|
||||
unsigned char panning;
|
||||
|
||||
unsigned char envelope_rate[6];
|
||||
unsigned char envelope_offset[6];
|
||||
|
||||
unsigned char tremolo_sweep;
|
||||
unsigned char tremolo_rate;
|
||||
unsigned char tremolo_depth;
|
||||
|
||||
unsigned char vibrato_sweep;
|
||||
unsigned char vibrato_rate;
|
||||
unsigned char vibrato_depth;
|
||||
|
||||
char modes;
|
||||
|
||||
short scale_frequency;
|
||||
unsigned short scale_factor;
|
||||
};
|
||||
|
||||
struct patch_info *patch;
|
||||
int spaceleft, totalspace;
|
||||
|
||||
void gus_reload_8_bit();
|
||||
|
||||
void gus_load(pgm)
|
||||
int pgm;
|
||||
{
|
||||
int i, j, patfd, offset;
|
||||
struct pat_header header;
|
||||
struct sample_header sample;
|
||||
char buf[256], name[256];
|
||||
struct stat info;
|
||||
|
||||
if (pgm < 0) {
|
||||
use8bit = force8bit;
|
||||
GUS_NUMVOICES(gus_dev, (card_info[gus_dev].nr_voices = 32));
|
||||
SEQ_DUMPBUF();
|
||||
for (i = 0; i < 256; i++)
|
||||
patchloaded[i] = 0;
|
||||
if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &gus_dev) == -1)
|
||||
{
|
||||
/* error: should quit */
|
||||
}
|
||||
spaceleft = gus_dev;
|
||||
ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &spaceleft);
|
||||
totalspace = spaceleft;
|
||||
}
|
||||
|
||||
if (patchloaded[pgm] < 0)
|
||||
return;
|
||||
|
||||
if (patchloaded[pgm] == 1)
|
||||
return;
|
||||
|
||||
if (gmvoice[pgm] == NULL) {
|
||||
patchloaded[pgm] = -1;
|
||||
return;
|
||||
}
|
||||
sprintf(name, PATCH_PATH1 "/%s.pat", gmvoice[pgm]);
|
||||
|
||||
if (stat(name, &info) == -1) {
|
||||
sprintf(name, PATCH_PATH2 "/%s.pat", gmvoice[pgm]);
|
||||
if (stat(name, &info) == -1)
|
||||
return;
|
||||
}
|
||||
if ((patfd = open(name, O_RDONLY, 0)) == -1)
|
||||
return;
|
||||
if (spaceleft < info.st_size) {
|
||||
if (!use8bit)
|
||||
gus_reload_8_bit();
|
||||
if (use8bit)
|
||||
if (spaceleft < info.st_size / 2) {
|
||||
close(patfd);
|
||||
patchloaded[pgm] = -1; /* no space for patch */
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (read(patfd, buf, 0xef) != 0xef) {
|
||||
close(patfd);
|
||||
return;
|
||||
}
|
||||
memcpy((char *) &header, buf, sizeof(header));
|
||||
|
||||
if (strncmp(header.magic, "GF1PATCH110", 12)) {
|
||||
close(patfd);
|
||||
return;
|
||||
}
|
||||
if (strncmp(header.version, "ID#000002", 10)) {
|
||||
close(patfd);
|
||||
return;
|
||||
}
|
||||
header.nr_waveforms = *(unsigned short *) &buf[85];
|
||||
header.master_volume = *(unsigned short *) &buf[87];
|
||||
|
||||
offset = 0xef;
|
||||
|
||||
for (i = 0; i < header.nr_waveforms; i++) {
|
||||
|
||||
if (lseek(patfd, offset, 0) == -1) {
|
||||
close(patfd);
|
||||
return;
|
||||
}
|
||||
if (read(patfd, &buf, sizeof(sample)) != sizeof(sample)) {
|
||||
close(patfd);
|
||||
return;
|
||||
}
|
||||
memcpy((char *) &sample, buf, sizeof(sample));
|
||||
|
||||
/*
|
||||
* Since some fields of the patch record are not 32bit aligned, we must
|
||||
* handle them specially.
|
||||
*/
|
||||
sample.low_note = *(int *) &buf[22];
|
||||
sample.high_note = *(int *) &buf[26];
|
||||
sample.base_note = *(int *) &buf[30];
|
||||
sample.detune = *(short *) &buf[34];
|
||||
sample.panning = (unsigned char) buf[36];
|
||||
|
||||
memcpy(sample.envelope_rate, &buf[37], 6);
|
||||
memcpy(sample.envelope_offset, &buf[43], 6);
|
||||
|
||||
sample.tremolo_sweep = (unsigned char) buf[49];
|
||||
sample.tremolo_rate = (unsigned char) buf[50];
|
||||
sample.tremolo_depth = (unsigned char) buf[51];
|
||||
|
||||
sample.vibrato_sweep = (unsigned char) buf[52];
|
||||
sample.vibrato_rate = (unsigned char) buf[53];
|
||||
sample.vibrato_depth = (unsigned char) buf[54];
|
||||
sample.modes = (unsigned char) buf[55];
|
||||
sample.scale_frequency = *(short *) &buf[56];
|
||||
sample.scale_factor = *(unsigned short *) &buf[58];
|
||||
|
||||
offset = offset + 96;
|
||||
patch = (struct patch_info *) malloc(sizeof(*patch) + sample.len);
|
||||
|
||||
if (patch == NULL) {
|
||||
close(patfd);
|
||||
return;
|
||||
}
|
||||
patch->key = GUS_PATCH;
|
||||
patch->device_no = gus_dev;
|
||||
patch->instr_no = pgm;
|
||||
patch->mode = sample.modes | WAVE_TREMOLO |
|
||||
WAVE_VIBRATO | WAVE_SCALE;
|
||||
patch->len = (use8bit ? sample.len / 2 : sample.len);
|
||||
patch->loop_start =
|
||||
(use8bit ? sample.loop_start / 2 : sample.loop_start);
|
||||
patch->loop_end = (use8bit ? sample.loop_end / 2 : sample.loop_end);
|
||||
patch->base_note = sample.base_note;
|
||||
patch->high_note = sample.high_note;
|
||||
patch->low_note = sample.low_note;
|
||||
patch->base_freq = sample.base_freq;
|
||||
patch->detuning = sample.detune;
|
||||
patch->panning = (sample.panning - 7) * 16;
|
||||
|
||||
memcpy(patch->env_rate, sample.envelope_rate, 6);
|
||||
for (j = 0; j < 6; j++) /* tone things down slightly */
|
||||
patch->env_offset[j] =
|
||||
(736 * sample.envelope_offset[j] + 384) / 768;
|
||||
|
||||
if (reverb)
|
||||
if (pgm < 120)
|
||||
patch->env_rate[3] = (2 << 6) | (12 - (reverb >> 4));
|
||||
else if (pgm > 127)
|
||||
patch->env_rate[1] = (3 << 6) | (63 - (reverb >> 1));
|
||||
|
||||
patch->tremolo_sweep = sample.tremolo_sweep;
|
||||
patch->tremolo_rate = sample.tremolo_rate;
|
||||
patch->tremolo_depth = sample.tremolo_depth;
|
||||
|
||||
patch->vibrato_sweep = sample.vibrato_sweep;
|
||||
patch->vibrato_rate = sample.vibrato_rate;
|
||||
patch->vibrato_depth = sample.vibrato_depth;
|
||||
|
||||
patch->scale_frequency = sample.scale_frequency;
|
||||
patch->scale_factor = sample.scale_factor;
|
||||
|
||||
patch->volume = header.master_volume;
|
||||
|
||||
if (lseek(patfd, offset, 0) == -1) {
|
||||
close(patfd);
|
||||
return;
|
||||
}
|
||||
if (read(patfd, patch->data, sample.len) != sample.len) {
|
||||
close(patfd);
|
||||
return;
|
||||
}
|
||||
if (patch->mode & WAVE_16_BITS && use8bit) {
|
||||
patch->mode &= ~WAVE_16_BITS;
|
||||
/* cut out every other byte to make 8-bit data from 16-bit */
|
||||
for (j = 0; j < patch->len; j++)
|
||||
patch->data[j] = patch->data[1 + j * 2];
|
||||
}
|
||||
SEQ_WRPATCH(patch, sizeof(*patch) + patch->len);
|
||||
free(patch);
|
||||
offset = offset + sample.len;
|
||||
}
|
||||
close(patfd);
|
||||
spaceleft = gus_dev;
|
||||
ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &spaceleft);
|
||||
patchloaded[pgm] = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
void gus_reload_8_bit()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &gus_dev) == -1)
|
||||
{
|
||||
/* error: should quit */
|
||||
}
|
||||
spaceleft = gus_dev;
|
||||
ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &spaceleft);
|
||||
totalspace = spaceleft;
|
||||
use8bit = 1;
|
||||
for (i = 0; i < 256; i++)
|
||||
if (patchloaded[i] > 0) {
|
||||
patchloaded[i] = 0;
|
||||
gus_load(i);
|
||||
}
|
||||
}
|
||||
|
||||
void adjustfm(buf, key)
|
||||
char *buf;
|
||||
int key;
|
||||
{
|
||||
unsigned char pan = ((rand() % 3) + 1) << 4;
|
||||
|
||||
if (key == FM_PATCH) {
|
||||
buf[39] &= 0xc0;
|
||||
if (buf[46] & 1)
|
||||
buf[38] &= 0xc0;
|
||||
buf[46] = (buf[46] & 0xcf) | pan;
|
||||
if (reverb) {
|
||||
unsigned val;
|
||||
val = buf[43] & 0x0f;
|
||||
if (val > 0)
|
||||
val--;
|
||||
buf[43] = (buf[43] & 0xf0) | val;
|
||||
}
|
||||
} else {
|
||||
int mode;
|
||||
if (buf[46] & 1)
|
||||
mode = 2;
|
||||
else
|
||||
mode = 0;
|
||||
if (buf[57] & 1)
|
||||
mode++;
|
||||
buf[50] &= 0xc0;
|
||||
if (mode == 3)
|
||||
buf[49] &= 0xc0;
|
||||
if (mode == 1)
|
||||
buf[39] &= 0xc0;
|
||||
if (mode == 2 || mode == 3)
|
||||
buf[38] &= 0xc0;
|
||||
buf[46] = (buf[46] & 0xcf) | pan;
|
||||
buf[57] = (buf[57] & 0xcf) | pan;
|
||||
if (mode == 1 && reverb) {
|
||||
unsigned val;
|
||||
val = buf[43] & 0x0f;
|
||||
if (val > 0)
|
||||
val--;
|
||||
buf[43] = (buf[43] & 0xf0) | val;
|
||||
val = buf[54] & 0x0f;
|
||||
if (val > 0)
|
||||
val--;
|
||||
buf[54] = (buf[54] & 0xf0) | val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadfm()
|
||||
{
|
||||
int sbfd, i, n, voice_size, data_size;
|
||||
char buf[60];
|
||||
struct sbi_instrument instr;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
fmloaded[i] = 0;
|
||||
srand(getpid());
|
||||
if (wantopl3) {
|
||||
voice_size = 60;
|
||||
sbfd = open(O3MELODIC, O_RDONLY, 0);
|
||||
} else {
|
||||
voice_size = 52;
|
||||
sbfd = open(SBMELODIC, O_RDONLY, 0);
|
||||
}
|
||||
if (sbfd == -1)
|
||||
{
|
||||
/* error: should quit */
|
||||
}
|
||||
instr.device = sb_dev;
|
||||
|
||||
for (i = 0; i < 128; i++) {
|
||||
if (read(sbfd, buf, voice_size) != voice_size)
|
||||
{
|
||||
/* error: should quit */
|
||||
}
|
||||
instr.channel = i;
|
||||
|
||||
if (strncmp(buf, "4OP", 3) == 0) {
|
||||
instr.key = OPL3_PATCH;
|
||||
data_size = 22;
|
||||
} else {
|
||||
instr.key = FM_PATCH;
|
||||
data_size = 11;
|
||||
}
|
||||
|
||||
fmloaded[i] = instr.key;
|
||||
|
||||
adjustfm(buf, instr.key);
|
||||
for (n = 0; n < 32; n++)
|
||||
instr.operators[n] = (n < data_size) ? buf[36 + n] : 0;
|
||||
|
||||
SEQ_WRPATCH(&instr, sizeof(instr));
|
||||
}
|
||||
close(sbfd);
|
||||
|
||||
if (wantopl3)
|
||||
sbfd = open(O3DRUMS, O_RDONLY, 0);
|
||||
else
|
||||
sbfd = open(SBDRUMS, O_RDONLY, 0);
|
||||
|
||||
for (i = 128; i < 175; i++) {
|
||||
if (read(sbfd, buf, voice_size) != voice_size)
|
||||
{
|
||||
/* error: should quit */
|
||||
}
|
||||
instr.channel = i;
|
||||
|
||||
if (strncmp(buf, "4OP", 3) == 0) {
|
||||
instr.key = OPL3_PATCH;
|
||||
data_size = 22;
|
||||
} else {
|
||||
instr.key = FM_PATCH;
|
||||
data_size = 11;
|
||||
}
|
||||
fmloaded[i] = instr.key;
|
||||
|
||||
adjustfm(buf, instr.key);
|
||||
for (n = 0; n < 32; n++)
|
||||
instr.operators[n] = (n < data_size) ? buf[n + 36] : 0;
|
||||
|
||||
SEQ_WRPATCH(&instr, sizeof(instr));
|
||||
}
|
||||
close(sbfd);
|
||||
}
|
||||
#endif /* linux || FreeBSD */
|
||||
217
project/jni/sdl_mixer/native_midi_gpl/playevents.c
Normal file
217
project/jni/sdl_mixer/native_midi_gpl/playevents.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/************************************************************************
|
||||
playevents.c -- actually sends sorted list of events to device
|
||||
|
||||
Copyright (C) 1994-1996 Nathan I. Laredo
|
||||
|
||||
This program is modifiable/redistributable under the terms
|
||||
of the GNU General Public Licence.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
Send your comments and all your spare pocket change to
|
||||
laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
|
||||
Kelly Drive, Lackland AFB, TX 78236-5128, USA.
|
||||
*************************************************************************/
|
||||
/* edited by Peter Kutak */
|
||||
/* email : kutak@stonline.sk */
|
||||
|
||||
#if defined(linux) || defined(__FreeBSD__)
|
||||
|
||||
#include "playmidi.h"
|
||||
#include <sys/time.h>
|
||||
|
||||
extern int seq_set_patch(int, int);
|
||||
extern void seq_key_pressure(int, int, int, int);
|
||||
extern void seq_start_note(int, int, int, int);
|
||||
extern void seq_stop_note(int, int, int, int);
|
||||
extern void seq_control(int, int, int, int);
|
||||
extern void seq_chn_pressure(int, int, int);
|
||||
extern void seq_bender(int, int, int, int);
|
||||
extern void seq_reset();
|
||||
|
||||
SEQ_USE_EXTBUF();
|
||||
extern int division, ntrks, format;
|
||||
extern int gus_dev, ext_dev, sb_dev, awe_dev, perc, seqfd, p_remap;
|
||||
extern int play_gus, play_fm, play_ext, play_awe, reverb, chorus, chanmask;
|
||||
extern int usevol[16];
|
||||
extern struct miditrack seq[MAXTRKS];
|
||||
extern float skew;
|
||||
extern unsigned long int default_tempo;
|
||||
extern char ImPlaying,StopPlease;
|
||||
extern void load_sysex(int, unsigned char *, int);
|
||||
|
||||
unsigned long int ticks, tempo;
|
||||
struct timeval start_time;
|
||||
|
||||
unsigned long int rvl(s)
|
||||
struct miditrack *s;
|
||||
{
|
||||
register unsigned long int value = 0;
|
||||
register unsigned char c;
|
||||
|
||||
if (s->index < s->length && ((value = s->data[(s->index)++]) & 0x80)) {
|
||||
value &= 0x7f;
|
||||
do {
|
||||
if (s->index >= s->length)
|
||||
c = 0;
|
||||
else
|
||||
value = (value << 7) +
|
||||
((c = s->data[(s->index)++]) & 0x7f);
|
||||
} while (c & 0x80);
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
|
||||
/* indexed by high nibble of command */
|
||||
int cmdlen[16] =
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0};
|
||||
|
||||
#define CMD seq[track].running_st
|
||||
#define TIME seq[track].ticks
|
||||
#define CHN (CMD & 0xf)
|
||||
#define NOTE data[0]
|
||||
#define VEL data[1]
|
||||
|
||||
int playevents()
|
||||
{
|
||||
unsigned long int tempo = default_tempo, lasttime = 0;
|
||||
unsigned int lowtime, track, best, length, loaded;
|
||||
unsigned char *data;
|
||||
double current = 0.0, dtime = 0.0;
|
||||
int use_dev, play_status, playing = 1;
|
||||
|
||||
seq_reset();
|
||||
gettimeofday(&start_time, NULL); /* for synchronization */
|
||||
for (track = 0; track < ntrks; track++) {
|
||||
seq[track].index = seq[track].running_st = 0;
|
||||
seq[track].ticks = rvl(&seq[track]);
|
||||
}
|
||||
for (best = 0; best < 16; best++) {
|
||||
if (ISAWE(best))
|
||||
use_dev = awe_dev;
|
||||
else if (ISGUS(best))
|
||||
use_dev = gus_dev;
|
||||
else if (ISFM(best))
|
||||
use_dev = sb_dev;
|
||||
else
|
||||
use_dev = ext_dev;
|
||||
seq_control(use_dev, best, CTL_BANK_SELECT, 0);
|
||||
seq_control(use_dev, best, CTL_EXT_EFF_DEPTH, reverb);
|
||||
seq_control(use_dev, best, CTL_CHORUS_DEPTH, chorus);
|
||||
seq_control(use_dev, best, CTL_MAIN_VOLUME, 127);
|
||||
seq_chn_pressure(use_dev, best, 127);
|
||||
seq_control(use_dev, best, 0x4a, 127);
|
||||
}
|
||||
SEQ_START_TIMER();
|
||||
SEQ_DUMPBUF();
|
||||
while (playing) {
|
||||
lowtime = ~0;
|
||||
for (best = track = 0; track < ntrks; track++)
|
||||
if (seq[track].ticks < lowtime) {
|
||||
best = track;
|
||||
lowtime = TIME;
|
||||
}
|
||||
if (lowtime == ~0)
|
||||
break; /* no more data to read */
|
||||
track = best;
|
||||
if (ISMIDI(CHN))
|
||||
use_dev = ext_dev;
|
||||
else if (ISAWE(CHN))
|
||||
use_dev = awe_dev;
|
||||
else if (ISGUS(CHN))
|
||||
use_dev = gus_dev;
|
||||
else
|
||||
use_dev = sb_dev;
|
||||
|
||||
/* this section parses data in midi file buffer */
|
||||
if ((seq[track].data[seq[track].index] & 0x80) &&
|
||||
(seq[track].index < seq[track].length))
|
||||
CMD = seq[track].data[seq[track].index++];
|
||||
if (CMD == 0xff && seq[track].index < seq[track].length)
|
||||
CMD = seq[track].data[seq[track].index++];
|
||||
if (CMD > 0xf7) /* midi real-time message (ignored) */
|
||||
length = 0;
|
||||
else if (!(length = cmdlen[(CMD & 0xf0) >> 4]))
|
||||
length = rvl(&seq[track]);
|
||||
|
||||
if (seq[track].index + length < seq[track].length) {
|
||||
/* use the parsed midi data */
|
||||
data = &(seq[track].data[seq[track].index]);
|
||||
if (CMD == set_tempo)
|
||||
tempo = ((*(data) << 16) | (data[1] << 8) | data[2]);
|
||||
if (TIME > lasttime) {
|
||||
if (division > 0) {
|
||||
dtime = ((double) ((TIME - lasttime) * (tempo / 10000)) /
|
||||
(double) (division)) * skew;
|
||||
current += dtime;
|
||||
lasttime = TIME;
|
||||
} else if (division < 0)
|
||||
current = ((double) TIME /
|
||||
((double) ((division & 0xff00 >> 8) *
|
||||
(division & 0xff)) * 10000.0)) * skew;
|
||||
/* stop if there's more than 40 seconds of nothing */
|
||||
if (dtime > 4096.0)
|
||||
playing = 0;
|
||||
else if ((int) current > ticks) {
|
||||
SEQ_WAIT_TIME((ticks = (int) current));
|
||||
SEQ_DUMPBUF();
|
||||
}
|
||||
}
|
||||
if (CMD > 0x7f && CMD < 0xf0 && ISPERC(CHN) && p_remap) {
|
||||
CMD &= 0xf0;
|
||||
CMD |= (p_remap - 1);
|
||||
}
|
||||
loaded = 0; /* for patch setting failures */
|
||||
if (playing && CMD > 0x7f && ISPLAYING(CHN))
|
||||
switch (CMD & 0xf0) {
|
||||
case MIDI_KEY_PRESSURE:
|
||||
if (ISPERC(CHN) && VEL && (!ISMIDI(CHN)&&!ISAWE(CHN)))
|
||||
loaded = seq_set_patch(CHN, NOTE + 128);
|
||||
if (loaded != -1)
|
||||
seq_key_pressure(use_dev, CHN, NOTE, VEL);
|
||||
break;
|
||||
case MIDI_NOTEON:
|
||||
if (ISPERC(CHN) && VEL && (!ISMIDI(CHN)&&!ISAWE(CHN)))
|
||||
loaded = seq_set_patch(CHN, NOTE + 128);
|
||||
if (VEL && usevol[CHN])
|
||||
VEL = usevol[CHN];
|
||||
if (loaded != -1)
|
||||
seq_start_note(use_dev, CHN, NOTE, VEL);
|
||||
break;
|
||||
case MIDI_NOTEOFF:
|
||||
seq_stop_note(use_dev, CHN, NOTE, VEL);
|
||||
break;
|
||||
case MIDI_CTL_CHANGE:
|
||||
seq_control(use_dev, CHN, NOTE, VEL);
|
||||
break;
|
||||
case MIDI_CHN_PRESSURE:
|
||||
seq_chn_pressure(use_dev, CHN, NOTE);
|
||||
break;
|
||||
case MIDI_PITCH_BEND:
|
||||
seq_bender(use_dev, CHN, NOTE, VEL);
|
||||
break;
|
||||
case MIDI_PGM_CHANGE:
|
||||
if (ISMIDI(CHN) || ISAWE(CHN) || !ISPERC(CHN))
|
||||
NOTE = seq_set_patch(CHN, NOTE);
|
||||
break;
|
||||
case MIDI_SYSTEM_PREFIX:
|
||||
if (length > 1)
|
||||
load_sysex(length, data, CMD);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* this last little part queues up the next event time */
|
||||
seq[track].index += length;
|
||||
if (seq[track].index >= seq[track].length)
|
||||
seq[track].ticks = ~0; /* mark track complete */
|
||||
else
|
||||
seq[track].ticks += rvl(&seq[track]);
|
||||
}
|
||||
SEQ_DUMPBUF();
|
||||
ImPlaying = 0;
|
||||
return 1;
|
||||
}
|
||||
#endif /* linux || FreeBSD */
|
||||
107
project/jni/sdl_mixer/native_midi_gpl/playmidi.h
Normal file
107
project/jni/sdl_mixer/native_midi_gpl/playmidi.h
Normal file
@@ -0,0 +1,107 @@
|
||||
#define RELEASE "Playmidi 2.4"
|
||||
/************************************************************************
|
||||
playmidi.h -- defines and structures for use by playmidi package
|
||||
|
||||
Copyright (C) 1994-1996 Nathan I. Laredo
|
||||
|
||||
This program is modifiable/redistributable under the terms
|
||||
of the GNU General Public Licence.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
Send your comments and all your spare pocket change to
|
||||
laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
|
||||
Kelly Drive, Lackland AFB, TX 78236-5128, USA.
|
||||
*************************************************************************
|
||||
/* edited by Peter Kutak */
|
||||
/* email : kutak@stonline.sk */
|
||||
|
||||
|
||||
/* Default mask for percussion instruments. Channels 16 and 10 = 0x8200 */
|
||||
#define PERCUSSION 0x0200
|
||||
/* change the following if you have lots of synth devices */
|
||||
#define MAX_CARDS 5
|
||||
/* the following definition is set by Configure */
|
||||
#define FM_DEFAULT_MODE 0
|
||||
/* the following definition is set by Configure */
|
||||
#define PATCH_PATH1 "/dos/ultrasnd/midi"
|
||||
/* the following definition is set by Configure */
|
||||
#define PATCH_PATH2 "/usr/local/lib/Plib"
|
||||
/* change this if you notice performance problems, 128 bytes by default */
|
||||
#define SEQUENCERBLOCKSIZE 128
|
||||
/* change this if you have really outrageous midi files > 128 tracks */
|
||||
/* 128 tracks is approximately a 4K structure */
|
||||
#define MAXTRKS 128
|
||||
/* where to find fm patch libraries */
|
||||
#define SEQUENCER_DEV "/dev/sequencer"
|
||||
#define O3MELODIC "/etc/std.o3"
|
||||
#define O3DRUMS "/etc/drums.o3"
|
||||
#define SBMELODIC "/etc/std.sb"
|
||||
#define SBDRUMS "/etc/drums.sb"
|
||||
#define ISPERC(x) (perc & (1 << x))
|
||||
#define ISGUS(x) (play_gus & (1 << x))
|
||||
#define ISFM(x) (play_fm & (1 << x))
|
||||
#define ISMIDI(x) (play_ext & (1 << x))
|
||||
#define ISAWE(x) (play_awe & (1 << x))
|
||||
#define ISPLAYING(x) (chanmask & (1 << x))
|
||||
#define NO_EXIT 100
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef linux
|
||||
#include <linux/awe_voice.h>
|
||||
#else
|
||||
#include <awe_voice.h>
|
||||
#endif
|
||||
|
||||
struct chanstate {
|
||||
int program;
|
||||
int bender;
|
||||
int oldbend; /* used for graphics */
|
||||
int bender_range;
|
||||
int oldrange; /* used for graphics */
|
||||
int controller[255];
|
||||
int pressure;
|
||||
};
|
||||
|
||||
struct voicestate {
|
||||
int note;
|
||||
int channel;
|
||||
int timestamp;
|
||||
int dead;
|
||||
};
|
||||
/* Non-standard MIDI file formats */
|
||||
#define RIFF 0x52494646
|
||||
#define CTMF 0x43544d46
|
||||
/* Standard MIDI file format definitions */
|
||||
#define MThd 0x4d546864
|
||||
#define MTrk 0x4d54726b
|
||||
#define meta_event 0xff
|
||||
#define sequence_number 0x00
|
||||
#define text_event 0x01
|
||||
#define copyright_notice 0x02
|
||||
#define sequence_name 0x03
|
||||
#define instrument_name 0x04
|
||||
#define lyric 0x05
|
||||
#define marker 0x06
|
||||
#define cue_point 0x07
|
||||
#define channel_prefix 0x20
|
||||
#define end_of_track 0x2f
|
||||
#define set_tempo 0x51
|
||||
#define smpte_offset 0x54
|
||||
#define time_signature 0x58
|
||||
#define key_signature 0x59
|
||||
#define sequencer_specific 0x74
|
||||
|
||||
struct miditrack {
|
||||
unsigned char *data; /* data of midi track */
|
||||
unsigned long int length; /* length of track data */
|
||||
unsigned long int index; /* current byte in track */
|
||||
unsigned long int ticks; /* current midi tick count */
|
||||
unsigned char running_st; /* running status byte */
|
||||
};
|
||||
|
||||
188
project/jni/sdl_mixer/native_midi_gpl/readmidi_native.c
Normal file
188
project/jni/sdl_mixer/native_midi_gpl/readmidi_native.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/************************************************************************
|
||||
readmidi.c -- last change: 1 Jan 96
|
||||
|
||||
Creates a linked list of each chunk in a midi file.
|
||||
ENTIRE MIDI FILE IS RETAINED IN MEMORY so that no additional malloc
|
||||
calls need be made to store the data of the events in the midi file.
|
||||
|
||||
Copyright (C) 1995-1996 Nathan I. Laredo
|
||||
|
||||
This program is modifiable/redistributable under the terms
|
||||
of the GNU General Public Licence.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
Send your comments and all your spare pocket change to
|
||||
laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
|
||||
Kelly Drive, Lackland AFB, TX 78236-5128, USA.
|
||||
*************************************************************************/
|
||||
/* edited by Peter Kutak */
|
||||
/* email : kutak@stonline.sk */
|
||||
|
||||
#if defined(linux) || defined(__FreeBSD__)
|
||||
|
||||
#include "playmidi.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int format, ntrks, division;
|
||||
unsigned char *midifilebuf;
|
||||
|
||||
/* the following few lines are needed for dealing with CMF files */
|
||||
int reloadfm = 0;
|
||||
extern void loadfm();
|
||||
extern int seqfd, sb_dev, wantopl3, play_fm, fmloaded[256];
|
||||
SEQ_USE_EXTBUF();
|
||||
|
||||
extern struct miditrack seq[MAXTRKS];
|
||||
extern unsigned long int default_tempo;
|
||||
|
||||
unsigned short Read16()
|
||||
{
|
||||
register unsigned short x;
|
||||
|
||||
x = (*(midifilebuf) << 8) | midifilebuf[1];
|
||||
midifilebuf += 2;
|
||||
return x;
|
||||
}
|
||||
|
||||
unsigned long Read32()
|
||||
{
|
||||
register unsigned long x;
|
||||
|
||||
x = (*(midifilebuf) << 24) | (midifilebuf[1] << 16) |
|
||||
(midifilebuf[2] << 8) | midifilebuf[3];
|
||||
midifilebuf += 4;
|
||||
return x;
|
||||
}
|
||||
|
||||
int readmidi(filebuf, filelength)
|
||||
unsigned char *filebuf;
|
||||
off_t filelength;
|
||||
{
|
||||
unsigned long int i = 0, track, tracklen;
|
||||
|
||||
midifilebuf = filebuf;
|
||||
/* allow user to specify header number in from large archive */
|
||||
#if 0
|
||||
while (i != find_header && midifilebuf < (filebuf + filelength - 32)) {
|
||||
if (strncmp(midifilebuf, "MThd", 4) == 0) {
|
||||
i++;
|
||||
midifilebuf += 4;
|
||||
} else
|
||||
midifilebuf++;
|
||||
}
|
||||
if (i != find_header) { /* specified header was not found */
|
||||
midifilebuf = filebuf;
|
||||
return find_header = 0;
|
||||
}
|
||||
#endif
|
||||
if (midifilebuf != filebuf)
|
||||
midifilebuf -= 4;
|
||||
i = Read32();
|
||||
if (i == RIFF) {
|
||||
midifilebuf += 16;
|
||||
i = Read32();
|
||||
}
|
||||
if (i == MThd) {
|
||||
tracklen = Read32();
|
||||
format = Read16();
|
||||
ntrks = Read16();
|
||||
division = Read16();
|
||||
} else if (i == CTMF) {
|
||||
/* load a creative labs CMF file, with instruments for fm */
|
||||
tracklen = midifilebuf[4] | (midifilebuf[5] << 8);
|
||||
format = 0;
|
||||
ntrks = 1;
|
||||
division = midifilebuf[6] | (midifilebuf[7] << 8);
|
||||
default_tempo = 1000000 * division /
|
||||
(midifilebuf[8] | (midifilebuf[9] << 8));
|
||||
seq[0].data = filebuf + tracklen;
|
||||
seq[0].length = filelength - tracklen;
|
||||
i = (unsigned long int) (*(short *) &midifilebuf[2]) - 4;
|
||||
/* if fm playback is enabled, load all fm patches from file */
|
||||
if (play_fm) {
|
||||
struct sbi_instrument instr;
|
||||
int j, k;
|
||||
reloadfm = midifilebuf[32]; /* number of custom patches */
|
||||
instr.device = sb_dev;
|
||||
for (j = 0; j < 32; j++)
|
||||
instr.operators[j] = 0x3f;
|
||||
instr.key = FM_PATCH;
|
||||
for (j = 0; j < reloadfm && j < 255; j++) {
|
||||
instr.channel = j;
|
||||
fmloaded[j] = instr.key;
|
||||
for (k = 0; k < 16; k++)
|
||||
instr.operators[k] = midifilebuf[i + (16 * j) + k];
|
||||
SEQ_WRPATCH(&instr, sizeof(instr));
|
||||
}
|
||||
}
|
||||
return ntrks;
|
||||
} else {
|
||||
int found = 0;
|
||||
while (!found && midifilebuf < (filebuf + filelength - 8))
|
||||
if (strncmp(midifilebuf, "MThd", 4) == 0)
|
||||
found++;
|
||||
else
|
||||
midifilebuf++;
|
||||
if (found) {
|
||||
midifilebuf += 4;
|
||||
tracklen = Read32();
|
||||
format = Read16();
|
||||
ntrks = Read16();
|
||||
division = Read16();
|
||||
} else {
|
||||
#ifndef DISABLE_RAW_MIDI_FILES
|
||||
/* this allows playing ANY file, so watch out */
|
||||
midifilebuf -= 4;
|
||||
format = 0; /* assume it's .mus file ? */
|
||||
ntrks = 1;
|
||||
division = 40;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (ntrks > MAXTRKS) {
|
||||
fprintf(stderr, "\nWARNING: %d TRACKS IGNORED!\n", ntrks - MAXTRKS);
|
||||
ntrks = MAXTRKS;
|
||||
}
|
||||
if (play_fm && reloadfm) {
|
||||
loadfm(); /* if custom CMF patches loaded, replace */
|
||||
reloadfm = 0;
|
||||
}
|
||||
for (track = 0; track < ntrks; track++) {
|
||||
if (Read32() != MTrk) {
|
||||
/* MTrk isn't where it's supposed to be, search rest of file */
|
||||
int fuzz, found = 0;
|
||||
midifilebuf -= 4;
|
||||
if (strncmp(midifilebuf, "MThd", 4) == 0)
|
||||
continue;
|
||||
else {
|
||||
if (!track) {
|
||||
seq[0].length = filebuf + filelength - midifilebuf;
|
||||
seq[0].data = midifilebuf;
|
||||
continue; /* assume raw midi data file */
|
||||
}
|
||||
midifilebuf -= seq[track - 1].length;
|
||||
for (fuzz = 0; (fuzz + midifilebuf) <
|
||||
(filebuf + filelength - 8) && !found; fuzz++)
|
||||
if (strncmp(&midifilebuf[fuzz], "MTrk", 4) == 0)
|
||||
found++;
|
||||
seq[track - 1].length = fuzz;
|
||||
midifilebuf += fuzz;
|
||||
if (!found)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
tracklen = Read32();
|
||||
if (midifilebuf + tracklen > filebuf + filelength)
|
||||
tracklen = filebuf + filelength - midifilebuf;
|
||||
seq[track].length = tracklen;
|
||||
seq[track].data = midifilebuf;
|
||||
midifilebuf += tracklen;
|
||||
}
|
||||
ntrks = track;
|
||||
return ntrks;
|
||||
}
|
||||
#endif /* linux || FreeBSD */
|
||||
Reference in New Issue
Block a user