⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qmus2mid.c

📁 The source code of Doom legacy for windows
💻 C
字号:
// Emacs style mode select   -*- C++ -*-//-----------------------------------------------------------------------------//// $Id: qmus2mid.c,v 1.6 2001/03/09 21:53:56 metzgermeister Exp $//// Copyright (C) 1995 by Sebastien Bacquet.// Portions Copyright (C) 1998-2000 by DooM Legacy Team.//// 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.////// $Log: qmus2mid.c,v $// Revision 1.6  2001/03/09 21:53:56  metzgermeister// *** empty log message ***//// Revision 1.5  2001/03/03 19:45:12  ydario// Do not compile under OS/2//// Revision 1.4  2000/10/08 13:30:01  bpereira// no message//// Revision 1.3  2000/09/10 10:46:15  metzgermeister// merged with SDL version//// Revision 1.2  2000/02/26 00:28:42  hurdler// Mostly bug fix (see borislog.txt 23-2-2000, 24-2-2000)////// DESCRIPTION://      convert Doom MUS data to a MIDI music data//      used by both DOS/WIN32////-----------------------------------------------------------------------------#ifndef __OS2__#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include "doomdef.h"#include "i_system.h"#include "byteptr.h"#include "m_swap.h"#include "qmus2mid.h"// MUS events#define MUS_EV_SCOREEND     6ULONG  TRACKBUFFERSIZE = 65536UL;  /* 64 Ko */struct Track track[16];static unsigned char MUS2MIDcontrol[15] ={        0,                  /* Program change - not a MIDI control change */        0x00,               /* Bank select */        0x01,               /* Modulation pot */        0x07,               /* Volume */        0x0A,               /* Pan pot */        0x0B,               /* Expression pot */        0x5B,               /* Reverb depth */        0x5D,               /* Chorus depth */        0x40,               /* Sustain pedal */        0x43,               /* Soft pedal */        0x78,               /* All sounds off */        0x7B,               /* All notes off */        0x7E,               /* Mono */        0x7F,               /* Poly */        0x79                /* Reset all controllers */};static byte    MUSchannel;static byte    MIDItrack;#define fwritemem(p,s,n,f)  memcpy(*f,p,n*s);*f+=(s*n)#define fwriteshort(x,f)    WRITESHORT(*f,((x>>8) & 0xff) | (x<<8))#define fwritelong(x,f)     WRITEULONG(*f,((x>>24) & 0xff) | ((x>>8) & 0xff00) | ((x<<8) & 0xff0000) | (x<<24))#define last(e)         ((unsigned char)(e & 0x80))#define event_type(e)   ((unsigned char)((e & 0x7F)>>4))#define channel(e)      ((unsigned char)(e & 0x0F))static void FreeTracks ( void ){    int i;    for (i = 0; i < 16; i++ )        if (track[i].data )            free( track[i].data );}static void TWriteByte (byte MIDItrack, char bbyte){    ULONG pos;    pos = track[MIDItrack].current;    if (pos < TRACKBUFFERSIZE )        track[MIDItrack].data[pos] = bbyte;    else        I_Error("Mus Convert Error : Track buffer full.\n");    track[MIDItrack].current++;}static void TWriteVarLen (byte tracknum, ULONG value){    ULONG buffer;    buffer = value & 0x7f;    while( (value >>= 7) )    {        buffer <<= 8;        buffer |= 0x80;        buffer += (value & 0x7f);    }    while( 1 )    {        TWriteByte( tracknum, (byte)buffer);        if (buffer & 0x80 )            buffer >>= 8;        else            break;    }}static int WriteMIDheader( USHORT ntrks, USHORT division, byte **file ){    fwritemem( MIDIMAGIC , 10, 1,file );    fwriteshort( ntrks, file);    fwriteshort( division, file );    return 0;}static void WriteTrack (int tracknum, byte **file){    USHORT size;    size_t quot, rem;    /* Do we risk overflow here ? */    size = (USHORT)track[tracknum].current + 4;    fwritemem( "MTrk", 4, 1, file );    if (!tracknum )        size += 33;    fwritelong( size, file );    if (!tracknum)    {        memset(*file,'\0',33);        *file+=33;    }    quot = (size_t) (track[tracknum].current / 4096);    rem = (size_t) (track[tracknum].current - quot*4096);    fwritemem (track[tracknum].data, 4096, quot, file );    fwritemem (((byte *) track[tracknum].data)+4096*quot, rem, 1, file );    fwritemem (TRACKMAGIC2, 4, 1, file );}static void WriteFirstTrack (byte **file){    USHORT size;    size = 43;    fwritemem( "MTrk", 4, 1, file );    fwritelong( size, file );    fwritemem( TRACKMAGIC3 , 4, 1, file );    memset(*file,'\0',22);    *file+=22;    fwritemem( TRACKMAGIC4, 6, 1, file );    fwritemem( TRACKMAGIC5, 7, 1, file );    fwritemem( TRACKMAGIC6, 4, 1, file );}static ULONG ReadTime( byte **file ){    ULONG time = 0;    int   bbyte;    do    {        bbyte = *(*file)++;        if (bbyte != EOF )            time = (time << 7) + (bbyte & 0x7F);    } while( (bbyte != EOF) && (bbyte & 0x80) );    return time;}// return first MIDI channel available, except percussion channel 9static char FirstChannelAvailable (char MUS2MIDchannel[]){    int i;    signed char max = -1;    // note: skip channel 15 which is percussions    for (i = 0; i < 15; i++ )        if (MUS2MIDchannel[i] > max )            max = MUS2MIDchannel[i];    // MIDI channel 9 is used for percussions    return (max == 8 ? 10 : max+1);}static void MidiEvent(byte NewEvent){    if ((NewEvent != track[MIDItrack].LastEvent) /*|| nocomp*/ )    {        TWriteByte( MIDItrack, NewEvent );        track[MIDItrack].LastEvent = NewEvent;    }}int qmus2mid (byte  *mus,               byte *mid,     // buffers in memory              USHORT division,               int BufferSize,               int nocomp,              int length,               int midbuffersize,              unsigned long* midilength)    //faB: returns midi file length in here{    byte*    file_mus;    byte*    file_mid;     // pointer in memory    static   MUSheader* MUSh;    byte     MIDIchannel;    byte     et;    USHORT   TrackCnt=0;    int      i, event, data;    ULONG    DeltaTime;    ULONG    TotalTime=0;    byte     MIDIchan2track[16];    char     MUS2MIDchannel[16];    char ouch = 0;    file_mus = mus;    file_mid = mid;    //r = ReadMUSheader (&MUSh, file_mus);    MUSh = (MUSheader *)mus;    if (strncmp (MUSh->ID, MUSMAGIC, 4))        return NOTMUSFILE;    //fseek( file_mus, MUSh.scoreStart, SEEK_SET );    file_mus = (char *)mus + MUSh->scoreStart;    if (MUSh->channels > 15)      /* <=> MUSchannels+drums > 16 */        return TOOMCHAN;    for (i=0; i<16; i++)    {        MUS2MIDchannel[i] = -1;        track[i].current = 0;        track[i].vel = 64;        track[i].DeltaTime = 0;        track[i].LastEvent = 0;        track[i].data = NULL;    }    if (BufferSize)        TRACKBUFFERSIZE = ((ULONG) BufferSize) << 10;    event = *(file_mus++);    et    = event_type (event);    MUSchannel = channel (event);    while ( (et != MUS_EV_SCOREEND) &&            file_mus-mus < length   &&     /*!feof( file_mus )*/            (event != EOF) )    {        if (MUS2MIDchannel[MUSchannel] == -1)        {            MIDIchannel = MUS2MIDchannel[MUSchannel] =                // if percussion use channel 9                (MUSchannel == 15 ? 9 : FirstChannelAvailable (MUS2MIDchannel) );            MIDItrack = MIDIchan2track[MIDIchannel] = (byte)TrackCnt++;            if (!(track[MIDItrack].data = (char *) malloc(TRACKBUFFERSIZE) ))            {                FreeTracks();                return MEMALLOC;            }        }        else        {            MIDIchannel = MUS2MIDchannel[MUSchannel];            MIDItrack   = MIDIchan2track [MIDIchannel];        }        TWriteVarLen( MIDItrack, track[MIDItrack].DeltaTime );        track[MIDItrack].DeltaTime = 0;        switch (et)        {        case 0 :                /* release note */            MidiEvent((byte)0x90 | MIDIchannel);                        data = *(file_mus++);            TWriteByte( MIDItrack, (byte)(data & 0x7F));            TWriteByte( MIDItrack, 0 );            break;                    case 1 :            MidiEvent((byte)0x90 | MIDIchannel);                        data = *(file_mus++);            TWriteByte( MIDItrack, (byte)(data & 0x7F));            if (data & 0x80)                track[MIDItrack].vel = (*file_mus++) & 0x7F;            TWriteByte( MIDItrack, track[MIDItrack].vel );            break;                    case 2 :            MidiEvent((byte)0xE0 | MIDIchannel);                        data = *(file_mus++);            TWriteByte( MIDItrack, (data & 1) << 6 );            TWriteByte( MIDItrack, data >> 1 );            break;        case 3 :            MidiEvent((byte)0xB0 | MIDIchannel);                        data = *(file_mus++);            TWriteByte( MIDItrack, MUS2MIDcontrol[data] );            if (data == 12 )                TWriteByte( MIDItrack, MUSh->channels+1 );            else                TWriteByte( MIDItrack, 0 );            break;        case 4 :            data = *(file_mus++);            if (data )            {                MidiEvent((byte)0xB0 | MIDIchannel);                                TWriteByte( MIDItrack, MUS2MIDcontrol[data] );            }            else  /* program change */                MidiEvent((byte)0xC0 | MIDIchannel);                        data = *(file_mus++);            TWriteByte( MIDItrack, data & 0x7F );            break;        case 5 :        case 7 :            FreeTracks();            return MUSFILECOR;        default : break;        }        if (last( event ) )        {            DeltaTime = ReadTime( &file_mus );            TotalTime += DeltaTime;            for (i = 0; i < (int) TrackCnt; i++ )                track[i].DeltaTime += DeltaTime;        }        event = *(file_mus++);        if (event != EOF )        {            et = event_type( event );            MUSchannel = channel( event );        }        else            ouch = 1;    }    if (!division)        division = 89;#ifndef SDL    for (i = 0; i < 16; i++)    {        if (track[i].current && track[i].data)        {            TWriteByte(i, (byte)0x00); // midi end of track code            TWriteByte(i, (byte)0xFF);            TWriteByte(i, (byte)0x2F);            TWriteByte(i, (byte)0x00);        }    }#endif    WriteMIDheader( TrackCnt+1, division, &file_mid );    WriteFirstTrack( &file_mid );    for (i = 0; i < (int) TrackCnt; i++ )        WriteTrack( i, &file_mid );    if (file_mid>mid+midbuffersize)        return MIDTOLARGE;    FreeTracks();    //faB: return lenght of Midi data    *midilength = (file_mid - mid);    return 0;}#endif // __OS2__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -