/*
MikMod Sound System
By Jake Stine of Divine Entertainment (1996-2000)
Support:
If you find problems with this code, send mail to:
[email protected]
Distribution / Code rights:
Use this source code in any fashion you see fit. Giving me credit where
credit is due is optional, depending on your own levels of integrity and
honesty.
-----------------------------------------
Module: LOAD_ABC
ABC module loader.
by Peter Grootswagers (2006)
<email:
[email protected]>
Portability:
All systems - all compilers (hopefully)
*/
#include <limits.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#ifndef _WIN32
#include <unistd.h> // for sleep
#endif // _WIN32
#ifdef NEWMIKMOD
#include "mikmod.h"
#include "uniform.h"
typedef UBYTE BYTE;
typedef UWORD WORD;
#else
#include "stdafx.h"
#include "sndfile.h"
#endif
#include "load_pat.h"
#define MAXABCINCLUDES 8
#define MAXCHORDNAMES 80
#define ABC_ENV_DUMPTRACKS "MMABC_DUMPTRACKS"
#define ABC_ENV_NORANDOMPICK "MMABC_NO_RANDOM_PICK"
// gchords use tracks with vpos 1 thru 7
// drums use track with vpos 8
// voice chords use vpos 0 and vpos from 11 up
#define GCHORDBPOS 1
#define GCHORDFPOS 2
#define GCHORDCPOS 3
#define DRUMPOS 8
#define DRONEPOS1 9
#define DRONEPOS2 10
// in the patterns a whole note at unmodified tempo is 16 rows
#define ROWSPERNOTE 16
// a 1/64-th note played in triool equals a 1/96-th note, to be able
// to play them and also to play the 1/64-th we need a resolution of 192
// because 2/192 = 1/96 and 3/192 = 1/64
#define RESOLUTION 192
#pragma pack(1)
/**************************************************************************
**************************************************************************/
#ifdef NEWMIKMOD
static char ABC_Version[] = "ABC+2.0 (draft IV)";
#endif
typedef enum {
note,
octave,
smpno,
volume,
effect,
effoper
} ABCEVENT_X_NOTE;
typedef enum {
none,
trill,
bow,
accent
} ABCEVENT_X_EFFECT;
typedef enum {
cmdflag,
command,
chordnum,
chordnote,
chordbase,
jumptype
} ABCEVENT_X_CMD;
typedef enum {
cmdsegno = '$',
cmdcapo = 'B',
cmdchord = 'C',
cmdfine = 'F',
cmdhide = 'H',
cmdjump = 'J',
cmdloop = 'L',
cmdcoda = 'O',
cmdpartbrk = 'P',
cmdsync = 'S',
cmdtempo = 'T',
cmdvariant = 'V',
cmdtocoda = 'X'
} ABCEVENT_CMD;
typedef enum {
jumpnormal,
jumpfade,
jumpdacapo,
jumpdcfade,
jumpdasegno,
jumpdsfade,
jumpfine,
jumptocoda,
jumpvariant,
jumpnot
} ABCEVENT_JUMPTYPE;
typedef struct _ABCEVENT
{
struct _ABCEVENT *next;
uint32_t tracktick;
union {
uint8_t par[6];
struct {
uint8_t flg;
uint8_t cmd;
uint32_t lpar; // for variant selections, bit pattern
};
};
uint8_t part;
uint8_t tiednote;
} ABCEVENT;
typedef struct _ABCTRACK
{
struct _ABCTRACK *next;
ABCEVENT *head;
ABCEVENT *tail;
ABCEVENT *capostart;
ABCEVENT *tienote;
int transpose;
int octave_shift;
uint32_t slidevoltime; // for crescendo and diminuendo
int slidevol; // -2:fade away, -1:diminuendo, 0:none, +1:crescendo
uint8_t vno; // 0 is track is free for use, from previous song in multi-songbook
uint8_t vpos; // 0 is main voice, other is subtrack for gchords, gchords or drumnotes
uint8_t tiedvpos;
uint8_t mute;
uint8_t chan; // 10 is percussion channel, any other is melodic channel
uint8_t volume;
uint8_t instr; // current instrument for this track
uint8_t legato;
char v[22]; // first twenty characters are significant
} ABCTRACK;
typedef struct _ABCMACRO
{
struct _ABCMACRO *next;
char *name;
char *subst;
char *n;
} ABCMACRO;
/**************************************************************************
**************************************************************************/
typedef struct _ABCHANDLE
{
#ifdef NEWMIKMOD
MM_ALLOC *allochandle;
MM_ALLOC *macrohandle;
MM_ALLOC *trackhandle;
MM_ALLOC *ho;
#endif
ABCMACRO *macro;
ABCMACRO *umacro;
ABCTRACK *track;
long int pickrandom;
unsigned int len;
int speed;
char *line;
char *beatstring;
uint8_t beat[4]; // a:first note, b:strong notes, c:weak notes, n:strong note every n
char gchord[80]; // last setting for gchord
char drum[80]; // last setting for drum
char drumins[80]; // last setting for drum
char drumvol[80]; // last setting for drum
uint32_t barticks;
// parse variables, declared here to avoid parameter pollution
int abcchordvol, abcchordprog, abcbassvol, abcbassprog;
int ktrans;
int drumon, gchordon, droneon;
int dronegm, dronepitch[2], dronevol[2];
ABCTRACK *tp, *tpc, *tpr;
uint32_t tracktime;
} ABCHANDLE;
static int global_voiceno, global_octave_shift, global_tempo_factor, global_tempo_divider;
static char global_part;
static uint32_t global_songstart;
/* Named guitar chords */
static char chordname[MAXCHORDNAMES][8];
static int chordnotes[MAXCHORDNAMES][6];
static int chordlen[MAXCHORDNAMES];
static int chordsnamed = 0;
static const char *sig[] = {
" C D EF G A Bc d ef g a b", // 7 sharps C#
" C D EF G AB c d ef g ab ", // 6 sharps F#
" C DE F G AB c de f g ab ", // 5 sharps B
" C DE F GA B c de f ga b ", // 4 sharps E
" CD E F GA B cd e f ga b ", // 3 sharps A
" CD E FG A B cd e fg a b ", // 2 sharps D
" C D E FG A Bc d e fg a b", // 1 sharps G
" C D EF G A Bc d ef g a b", // 0 sharps C
" C D EF G AB c d ef g ab ", // 1 flats F
" C DE F G AB c de f g ab ", // 2 flats Bb
" C DE F GA B c de f ga b ", // 3 flats Eb
" CD E F GA B cd e f ga b ", // 4 flats Ab
" CD E FG A B cd e fg a b ", // 5 flats Db
"C D E FG A Bc d e fg a b ", // 6 flats Gb
"C D EF G A Bc d ef g a b ", // 7 flats Cb
// 0123456789012345678901234
};
static const char *keySigs[] = {
/* 0....:....1....:....2....:....3....:....4....:....5. */
"7 sharps: C# A#m G#Mix D#Dor E#Phr F#Lyd B#Loc ",
"6 sharps: F# D#m C#Mix G#Dor A#Phr BLyd E#Loc ",
"5 sharps: B G#m F#Mix C#Dor D#Phr ELyd A#Loc ",
"4 sharps: E C#m BMix F#Dor G#Phr ALyd D#Loc ",
"3 sharps: A F#m EMix BDor C#Phr DLyd G#Loc ",
"2 sharps: D Bm AMix EDor F#Phr GLyd C#Loc ",
"1 sharp : G Em DMix ADor BPhr CLyd F#Loc ",
"0 sharps: C Am GMix DDor EPhr FLyd BLoc ",
"1 flat : F Dm CMix GDor APhr BbLyd ELoc ",
"2 flats : Bb Gm FMix CDor DPhr EbLyd ALoc ",
"3 flats : Eb Cm BbMix FDor GPhr AbLyd DLoc ",
"4 flats : Ab Fm EbMix BbDor CPhr DbLyd GLoc ",
"5 flats : Db Bbm AbMix EbDor FPhr GbLyd CLoc ",
"6 flats : Gb Ebm DbMix AbDor BbPhr CbLyd FLoc ",
"7 flats : Cb Abm GbMix DbDor EbPhr FbLyd BbLoc ",
0
};
// local prototypes
static int abc_getnumber(const char *p, int *number);
static ABCTRACK *abc_locate_track(ABCHANDLE *h, const char *voice, int pos);
static void abc_add_event(ABCHANDLE *h, ABCTRACK *tp, ABCEVENT *e);
static void abc_add_setloop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime);
static void abc_add_setjumploop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, ABCEVENT_JUMPTYPE j);
static uint32_t abc_pattracktime(ABCHANDLE *h, uint32_t tracktime);
static int abc_patno(ABCHANDLE *h, uint32_t tracktime);
#ifndef HAVE_SETENV
static void setenv(const char *name, const char *value, int overwrite)
{
int len = strlen(name)+1+strlen(value)+1;
char *str = (char *)malloc(len);
sprintf(str, "%s=%s", name, value);
putenv(str);
free(str);
}
#endif
static int abc_isvalidchar(char c) {
return(isalpha(c) || isdigit(c) || isspace(c) || c == '%' || c == ':');
}
static const char *abc_skipspace(const char *p)
{
while (*p && isspace(*p))
p++;
return p;
}
static void abc_extractkeyvalue(char *key, size_t key_max,
char *value, size_t value_max, const char *src)
{
while (*src && isspace(*src))
src++;
size_t key_size;
for (key_size = 0; key_size < key_max - 1 && *src;) {
if (*src == '=') {
src++;
break;
}
key[key_size++] = *src++;
}
while (key_size > 0 && isspace(key[key_size - 1]))
key_size--;
key[key_size] = '\0';
while (*src && issp
- 1
- 2
前往页