
// gfxsound.cpp
//
// Copyright (c) 1996 by Toshiaki Tsuji, all rights reserved.

#include "stdgfx.h"
#include "gfxsound.h"

SOUND Sound;

SOUND::SOUND ()
  {
  } // End of Constructor for SOUND

SOUND::~SOUND ()
  {
  } // End of Destructor for SOUND

VOID SOUND::ReverseWORD ( SHORT *Word )
  {
    BYTE Hi,Lo;
    Hi = (BYTE)((*Word)>>8);
    Lo = (BYTE)((*Word)&0xFF);
    *Word = Lo;
    (*Word) <<= 8;
    *Word = Hi;
  } // End of ReverseWORD for SOUND

VOID SOUND::ReverseDWORD ( DWORD *DWord )
  {
         SHORT Hi,Lo;
         Hi = (SHORT)((*DWord)>>16);
         Lo = (SHORT)((*DWord)&0xFFFF);
         ReverseWORD ( &Hi );
         ReverseWORD ( &Lo );
         *DWord = Lo;
         (*DWord) <<= 16;
         *DWord = Hi;
  } // End of ReverseDWORD for SOUND

BOOLEAN SOUND::ReadMIDIChunk ( FILEHANDLE f, MIDICHUNK *Chunk )
  {
         if (File.Read ( f, Chunk, sizeof ( MIDICHUNK ) )==FAILURE)
                return FAILURE;
         ReverseDWORD ( (DWORD*)&(Chunk->Length ) );

         return TRUE;
  } // End of ReadMIDIChunk for SOUND

BOOLEAN SOUND::ReadMIDIHeader ( FILEHANDLE f, MIDIHEADER *Header )
  {
         if (ReadMIDIChunk ( f, &(Header->Chunk) )==FAILURE)
                return FAILURE;

         if (strncmp ( Header->Chunk.Name, "MThd", 4 )!=0)
                return FAILURE;

         // Get MIDI File Type
         SHORT Type;
         File.Read ( f, &Type, sizeof (SHORT ) );
         ReverseWORD ( &Type );
         Header->Type = Type;

         // Get number of Tracks
         SHORT NumTracks;
         File.Read ( f, &NumTracks, sizeof (SHORT ) );
         ReverseWORD ( &NumTracks );
         Header->NumTracks = NumTracks;

         SHORT Time;
         File.Read ( f, &Time, sizeof (SHORT ) );
         ReverseWORD ( &Time );
         Header->Time = Time;

         return TRUE;
  } // End of ReadMIDIHeader for SOUND

BOOLEAN SOUND::ReadMIDITrack ( FILEHANDLE f, MIDITRACK *Track )
  {
         if (ReadMIDIChunk ( f, &(Track->Chunk) )==FAILURE)
                return FAILURE;

         if (strncmp ( Track->Chunk.Name, "MTrk", 4 )!=0)
                return FAILURE;

         if (File.Read ( f, &(Track->NumEvents), sizeof(SHORT) )==FAILURE)
                return FAILURE;
         ReverseWORD ( &(Track->NumEvents) );

         LONG i;
         Track->Events = new MIDIEVENTTYPE [Track->NumEvents];
         if (Track->Events==NULL)
                return FAILURE;

         for (i=0;i<Track->NumEvents;i++)
                {
                  if (ReadMIDIEvent ( f, &(Track->Events[i]) )==FAILURE)
          return FAILURE;
                } // End for
         return TRUE;
  } // End of ReadMIDITrack for SOUND

BOOLEAN SOUND::ReadMIDIEvent ( FILEHANDLE f, MIDIEVENTTYPE *Event )
  {
    Event->DeltaTime = ReadMIDIDeltaTime ( f );
    return TRUE;
  } // End of ReadMIDIEvent for SOUND

DWORD SOUND::ReadMIDIDeltaTime ( FILEHANDLE f )
  {
    BYTE Byte1,Byte2,Byte3,Byte4;

    Byte1 = Byte2 = Byte3 = Byte4 = 0;

    File.Read ( f, &Byte1, sizeof(BYTE) );
    if (Byte1&0x80)
                {
                  File.Read ( f, &Byte2, sizeof(BYTE) );
                  if (Byte2&0x80)
                         {
                                File.Read ( f, &Byte3, sizeof(BYTE) );
                                if (Byte3&0x80)
                                  {
                                         File.Read ( f, &Byte4, sizeof(BYTE) );
                                  } // End if
                         } // End if
                } // End if

    DWORD Time;
         Time = ((LONG)Byte1<<24)+((LONG)Byte2<<16)+((LONG)Byte3<<8)
                                +(LONG)Byte4;

         ReverseDWORD ( &Time );
    return Time;
  } // End of ReadMIDIDeltaTime for SOUND

BOOLEAN SOUND::LoadMIDI ( STRING FileName )
  {
         FILEHANDLE f;

         f = File.Open ( FileName, OPEN_READ | OPEN_BINARY );
         if (f==NULL)
                return FAILURE;

         MIDIHEADER Header;

         if (ReadMIDIHeader ( f, &Header )==FAILURE)
                {
                  File.Close ( f );
                  return FAILURE;
                } // End if

         LONG i;
         MIDITRACK *Tracks;
         Tracks = new MIDITRACK [Header.NumTracks];
         if (Tracks==NULL)
                {
                  File.Close ( f );
                  return FAILURE;
                } // End if

         for (i=0;i<Header.NumTracks;i++)
                {
                  if (ReadMIDITrack ( f, &Tracks[i] )==FAILURE)
                         {
                                File.Close ( f );
            return FAILURE;
                         } // End if
                } // End for

         File.Close ( f );
         return TRUE;
  } // End of LoadMIDI for SOUND

