/****************************************************************************\ * * * DEMO Sample Demo for SB AWE32 Developer's Information Package * * * * (C) Copyright Creative Technology Ltd. 1992-94. All rights reserved * * worldwide. * * * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * * PURPOSE. * * * * You have a royalty-free right to use, modify, reproduce and * * distribute the Sample Files (and/or any modified version) in * * any way you find useful, provided that you agree to * * the Creative's Software Licensing Aggreement and you also agree that * * Creative has no warranty obligations or liability for any Sample Files. * * * \****************************************************************************/ /****************************************************************************\ * File name : DEMO.C * * * * Programmer : Tan Khir Hien * * Creative Technology Ltd, 1994. All rights reserved. * * * \****************************************************************************/ #include #include #include #include #include #include "ctaweapi.h" /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ C O M P I L E R D E P E N D E N C I E S ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ #if defined(__TURBOC__) #define _inp inportb #define _outp outportb #endif #if defined(__WATCOMC__) #define _inp inp #define _outp outp #endif #if defined(__HIGHC__) #define kbhit _kbhit #define getch _getch #define memicmp _memicmp #pragma Align_members(1) #endif #if defined(__SC__) #define _inp inp #define _outp outp #endif /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ D E F I N E S ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ /* DSP defines */ #define MPU_ACK_OK 0xfe #define MPU_RESET_CMD 0xff #define MPU_ENTER_UART 0x3f /* PIC defines */ #define PIC1Ack 0x20 #define PIC1Mask 0x21 #define PIC2Ack 0xa0 #define PIC2Mask 0xa1 #define PIC1IntBase 0x08 #define PIC2IntBase 0x70 #define PIC2IRQChain 0x02 /* MIDI states */ #define READING 0 #define SYSEX 1 #define UNDEFINED 2 /* macros */ #define SBCPort(x) ((x)+wSBCBaseAddx) #define MPUPort(x) ((x)+wMpuBaseAddx) /* WAV header */ typedef struct { DWORD dwFileID; DWORD dwFileLen; DWORD dwFormatType; DWORD dwFormatID; DWORD dwFormatLen; WORD wFormatTag; WORD wChannels; DWORD dwSamplesPerSec; DWORD dwAvgSample; WORD wBlockAlign; WORD wBitsPerSample; } PCMRIFF; /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ G L O B A L V A R I A B L E S ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ WORD wSBCBaseAddx = 0x220; /* Sound Blaster base address */ WORD wEMUBaseAddx = 0x620; /* EMU8000 subsystem base address */ WORD wMpuBaseAddx = 0x330; /* MPU401 base address */ WORD wMIDIRecv = 0; /* Number of MIDI bytes received */ WORD wMIDIState = UNDEFINED; /* MIDI parsing state */ BYTE bMIDIBuf[32] = {0}; /* MIDI read buffer */ BYTE bMIDIMsgLen[] = {3, 3, 3, 3, 2, 2, 3, 0}; /* SoundFont variables */ WAVE_PACKET wpWave = {0}; SOUND_PACKET spSound = {0}; char* pPresets[MAXBANKS] = {0}; LONG lBankSizes[MAXBANKS] = {0}; char Packet[PACKETSIZE] = {0}; /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ InitSoundBlaster ³*/ /*³ Initializes Sound Blaster to ready to receive data state. ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ BOOL InitSoundBlaster (void) { volatile DWORD dwCount; for (dwCount=0; dwCount<0x2000; dwCount++) ; dwCount = 0x2000; while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; _outp(MPUPort(1), MPU_RESET_CMD); for (dwCount=0; dwCount<0x2000; dwCount++) ; dwCount = 0x2000; while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount; _inp(MPUPort(0)); for (dwCount=0; dwCount<0x2000; dwCount++) ; dwCount = 0x2000; while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; _outp(MPUPort(1), MPU_RESET_CMD); for (dwCount=0; dwCount<0x2000; dwCount++) ; dwCount = 0x2000; while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount; _inp(MPUPort(0)); for (dwCount=0; dwCount<0x2000; dwCount++) ; dwCount = 0x2000; while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; _outp(MPUPort(1), MPU_ENTER_UART); for (dwCount=0; dwCount<0x2000; dwCount++) ; dwCount = 0x2000; while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount; if (!dwCount) return TRUE; if (_inp(MPUPort(0)) != MPU_ACK_OK) return TRUE; /* mask MPU-401 interrupt */ _outp(SBCPort(0x4), 0x83); _outp(SBCPort(0x5), _inp(SBCPort(0x5)) & ~0x04); return FALSE; } /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ CleanUpSoundBlaster ³*/ /*³ Cleans up Sound Blaster to normal state. ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ void CleanUpSoundBlaster (void) { volatile DWORD dwCount; for (dwCount=0; dwCount<0x2000; dwCount++) ; dwCount = 0x2000; while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; _outp(MPUPort(1), MPU_RESET_CMD); for (dwCount=0; dwCount<0x2000; dwCount++) ; _inp(MPUPort(0)); for (dwCount=0; dwCount<0x2000; dwCount++) ; dwCount = 0x2000; while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; _outp(MPUPort(1), MPU_RESET_CMD); for (dwCount=0; dwCount<0x2000; dwCount++) ; _inp(MPUPort(0)); } /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ GetHexWord ³*/ /*³ Convert hex string into WORD. ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ WORD GetHexWord(const char ** s) { WORD n = 0; while (**s) { if (**s >= '0' && **s <= '9') n = n * 16 + (*(*s)++ - '0'); else if (**s >= 'a' && **s <= 'f') n = n * 16 + (*(*s)++ - 'a') + 10; else if (**s >= 'A' && **s <= 'F') n = n * 16 + (*(*s)++ - 'A') + 10; else break; } return n; } /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ GetEnvSettings ³*/ /*³ Searches the base addresses of sound blaster card. ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ void GetEnvSettings (void) { WORD srcAddx = 0xffff; WORD mpuAddx = 0xffff; WORD emuAddx = 0xffff; const char* szBlaster; szBlaster = getenv("BLASTER"); if (!szBlaster) return; while (*szBlaster) { if (*szBlaster == 'a' || *szBlaster == 'A') { ++szBlaster; if (*szBlaster) { if (*szBlaster == ':') ++szBlaster; srcAddx = GetHexWord(&szBlaster); } } if (*szBlaster == 'e' || *szBlaster == 'E') { ++szBlaster; if (*szBlaster) { if (*szBlaster == ':') ++szBlaster; emuAddx = GetHexWord(&szBlaster); } } if (*szBlaster == 'p' || *szBlaster == 'P') { ++szBlaster; if (*szBlaster) { if (*szBlaster == ':') ++szBlaster; mpuAddx = GetHexWord(&szBlaster); } } /* skip until blank or end of string */ while (*szBlaster && *szBlaster != ' ') ++szBlaster; while (*szBlaster == ' ') ++szBlaster; } if (mpuAddx != 0xffff) wMpuBaseAddx = mpuAddx; if (srcAddx != 0xffff) wSBCBaseAddx = srcAddx; if (emuAddx != 0xffff) wEMUBaseAddx = emuAddx; else if (srcAddx != 0xffff) wEMUBaseAddx = srcAddx + 0x400; } /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ OpenSBK ³*/ /*³ Locate and open a SBK file. ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ FILE* OpenSBK (const char* szSBKFile) { FILE* fp; char szFilePath[80]; const char* szSoundEnv; szSoundEnv = getenv("SOUND"); if (szSoundEnv) { strcpy(szFilePath, szSoundEnv); strcat(szFilePath, "\\SFBANK\\"); strcat(szFilePath, szSBKFile); fp = fopen(szFilePath, "rb"); if (fp) return fp; } return fopen(szSBKFile, "rb"); } /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ LoadSBK ³*/ /*³ Scan the command line to load the specified SBK file ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ int LoadSBK(int argc, char** argv) { int i; FILE* fp; char szSBKFile[40]; for (i=1; i spSound.total_patch_ram) { fclose(fp); printf("ERROR: Not enough patch ram to load %s\n", argv[i]); return TRUE; } /* allocate patch ram */ bank = spSound.total_banks; lBankSizes[bank] = sampsize + 80; if (riff.wBitsPerSample == 8) lBankSizes[bank] *= 2; spSound.total_patch_ram -= lBankSizes[bank]; spSound.total_banks += 1; awe32DefineBankSizes(&spSound); /* setup WAVE_PACKET */ wpWave.tag = 0x101; wpWave.bank_no = (SHORT) bank; wpWave.data = Packet; wpWave.sample_size = (riff.wBitsPerSample == 16) ? sampsize/2 : sampsize; wpWave.samples_per_sec = riff.dwSamplesPerSec; wpWave.bits_per_sample = riff.wBitsPerSample; wpWave.no_channels = 1; wpWave.looping = 0; wpWave.startloop = 0; wpWave.endloop = wpWave.sample_size; wpWave.release = 0; /* request to load WAV */ if (awe32WPLoadRequest(&wpWave)) { fclose(fp); printf("ERROR: Request to load %s failed\n", argv[i]); return TRUE; } /* stream the raw PCM samples */ wpWave.data = Packet; do fread(Packet, 1, PACKETSIZE, fp); while (!awe32WPStreamWave(&wpWave)); fclose(fp); /* build SoundFont preset objects */ pPresets[bank] = (char*) malloc(wpWave.preset_size); wpWave.presets = pPresets[bank]; if (awe32WPBuildSFont(&wpWave)) { printf("ERROR: Cannot build SoundFont preset objects\n"); return TRUE; } } return FALSE; } /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ SendMidi ³*/ /*³ Send Midi event to MIDI engine ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ void SendMidi (void) { switch (bMIDIBuf[0] >> 4) { case 0x8: awe32NoteOff((WORD) bMIDIBuf[0]&15, bMIDIBuf[1], bMIDIBuf[2]); break; case 0x9: awe32NoteOn((WORD) bMIDIBuf[0]&15, bMIDIBuf[1], bMIDIBuf[2]); break; case 0xa: awe32PolyKeyPressure((WORD) bMIDIBuf[0]&15, bMIDIBuf[1], bMIDIBuf[2]); break; case 0xb: awe32Controller((WORD) bMIDIBuf[0]&15, bMIDIBuf[1], bMIDIBuf[2]); break; case 0xc: awe32ProgramChange((WORD) bMIDIBuf[0]&15, bMIDIBuf[1]); break; case 0xd: awe32ChannelPressure((WORD) bMIDIBuf[0]&15, bMIDIBuf[1]); break; default: awe32PitchBend((WORD) bMIDIBuf[0]&15, bMIDIBuf[1], bMIDIBuf[2]); break; } } /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ SendSysEx ³*/ /*³ Send SysEx event to MIDI engine ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ void SendSysEx (void) { awe32Sysex(0, bMIDIBuf, wMIDIRecv); } /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ ProcessMidi ³*/ /*³ MIDI stream processing ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ void ProcessMidi (BYTE bMidi) { if (bMidi & 0x80) { if (bMidi == 0xf7 && wMIDIState == SYSEX) { bMIDIBuf[wMIDIRecv++] = bMidi; SendSysEx(); wMIDIRecv = 1; return; } wMIDIRecv = 0; bMIDIBuf[wMIDIRecv++] = bMidi; if ((bMidi >> 4) != 0xf) wMIDIState = READING; else wMIDIState = (WORD) ((bMidi == 0xf0) ? SYSEX : UNDEFINED); return; } if (wMIDIState == UNDEFINED) return; bMIDIBuf[wMIDIRecv++] = bMidi; if (wMIDIState == SYSEX) { if (wMIDIRecv == 32) wMIDIState = UNDEFINED; } else if (wMIDIRecv == (WORD) bMIDIMsgLen[(bMIDIBuf[0]>>4)-8]) { SendMidi(); wMIDIRecv = 1; } } /*ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ*/ /*³ main ³*/ /*³ Where the fun begins... ³*/ /*ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ*/ int main(int argc, char** argv) { int i; int k, key; int ret = 1; printf("\n"); printf("SB AWE32 Developer's Information Pack\n"); printf("DOS Real/Protected Mode API demonstration\n"); printf("Copyright (c) Creative Technology Ltd., 1994.\n"); printf("\n"); if (argc == 1) printf("Usage: DEMO [/SBK:sbkfile] [wav1.wav ...]\n\n", argv[0]); GetEnvSettings(); if (awe32Detect(wEMUBaseAddx)) { printf("ERROR: SB AWE32 not detected\n"); return ret; } if (awe32InitHardware()) { printf("ERROR: SB AWE32 initialization failed\n"); return ret; } if (InitSoundBlaster()) { printf("ERROR: MPU401 initialization failed\n"); return ret; } awe32TotalPatchRam(&spSound); if (LoadSBK(argc, argv)) goto cleanup; /* load SBK file */ if (LoadWAV(argc, argv)) goto cleanup; /* load any specified WAV file */ awe32InitMIDI(); awe32InitNRPN(); /* pull in NRPN.OBJ and NRPNVAR.OBJ */ ret = 0; key = 1; for (i=1; i to stop ...\n"); loop: if (kbhit()) { k = getch(); if (k == 27) goto cleanup; k = k - '0'; if (k > 0 && k < key) { awe32Controller(15, 0, (WORD) k); awe32ProgramChange(15, 0); awe32NoteOn(15, 60, 127); } } if ((_inp(MPUPort(1)) & 0x80) == 0) ProcessMidi((BYTE) _inp(MPUPort(0))); goto loop; cleanup: /* free allocated memory */ awe32ReleaseAllBanks(&spSound); for (i=0; i