#pragma once #include "..\munga\style.h" #include "..\munga\node.h" #include "..\munga\schain.h" #include "..\munga\audio.h" #include "openal/al.h" struct SourceSet { int count; ALuint sources[5]; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ typedef unsigned char MIDIStatus; typedef unsigned char MIDIChannel; typedef unsigned char MIDIValue; typedef int MIDIPitchBend; typedef int MIDINRPNValue; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI status ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define MIDI_CHANNEL_COUNT (16) #define MIDI_NOTE_OFF_STATUS ((MIDIValue)0x8) // 8 #define MIDI_NOTE_ON_STATUS ((MIDIValue)0x9) // 9 #define MIDI_POLYKEY_STATUS ((MIDIValue)0xa) // 10 #define MIDI_CONTROLLER_STATUS ((MIDIValue)0xb) // 11 #define MIDI_PROGRAM_CHANGE_STATUS ((MIDIValue)0xc) // 12 #define MIDI_CHANNEL_PRESSURE_STATUS ((MIDIValue)0xd) // 13 #define MIDI_PITCH_BEND_STATUS ((MIDIValue)0xe) // 14 //~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI controllers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define MIDI_MAX_CONTROL_VALUE ((MIDIValue)127) #define MIDI_MIN_CONTROL_VALUE ((MIDIValue)0) #define MIDI_LEFT_PAN_VALUE ((MIDIValue)0) #define MIDI_CENTER_PAN_VALUE ((MIDIValue)63) #define MIDI_RIGHT_PAN_VALUE ((MIDIValue)127) #define MIDI_VOLUME_CONTROL ((MIDIValue)7) #define MIDI_PAN_CONTROL ((MIDIValue)10) #define MIDI_REVERB_CONTROL ((MIDIValue)91) #define MIDI_CHORUS_CONTROL ((MIDIValue)93) #define MIDI_CONTROL_RESET ((MIDIValue)121) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI notes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define MIDI_DEFAULT_NOTE ((MIDIValue)60) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI pitch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define MIDI_PITCH_BEND_MAX ((MIDIPitchBend)8191) #define MIDI_PITCH_BEND_RANGE ((MIDIValue)24) #define MIDI_PITCH_BEND_CENTS (24*100) #define MIDI_PITCH_PER_CENTS ((Scalar)MIDI_PITCH_BEND_MAX / (Scalar)MIDI_PITCH_BEND_CENTS) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AWE NRPN ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define AWE_VOL_ATTACK_TIME_NRPN ((MIDIValue)11) #define AWE_PITCH_NRPN ((MIDIValue)16) #define AWE_FILTER_CUTOFF_NRPN ((MIDIValue)21) #define AWE_VOL_ATTACK_TIME_RANGE ((MIDINRPNValue)5940) // 0...5.9 secs #define AWE_FILTER_CUTOFF_RANGE ((MIDINRPNValue)127) // 100...8000 Hz //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AWE effects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ typedef enum { ChorusMIDIEffectType, ReverbMIDIEffectType } MIDIEffectType; //~~~~~~~~~~~~~~~~~~~~~~~~~~~ AWE resources ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define AWE_VOICE_COUNT (32) #define AWE_CHANNEL_COUNT (16) #define AWE_PERCUSSIVE_CHANNEL (9) // // Driver type to use // #define _MIDI_DRIVER_TYPE _MIDI_AWE32 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDIMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define MIDI_MESSAGE_SIZE (3) class MIDIMessage SIGNATURED { friend class AudioCard; friend std::ostream& operator << (std::ostream &strm, const MIDIMessage &midi_message); public: MIDIMessage(MIDIStatus status, MIDIChannel channel, MIDIValue byte1, MIDIValue byte2 = 0); ~MIDIMessage() {} Logical TestInstance() const; private: MIDIValue message[MIDI_MESSAGE_SIZE]; }; inline MIDIMessage::MIDIMessage(MIDIStatus status, MIDIChannel channel, MIDIValue byte1, MIDIValue byte2) { message[0] = (MIDIValue)((status << 4) | channel); message[1] = byte1; message[2] = byte2; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioChannel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ typedef enum { InstrumentAudioChannelType = 0, PercussionAudioChannelType } AudioChannelType; class AudioCard; /*class AudioChannel : public Plug { public: // //-------------------------------------------------------------------- // Constructor, Destructor, Testing //-------------------------------------------------------------------- // AudioChannel(AudioChannelType audio_channel_type, MIDIChannel midi_channel, AudioCard *audio_card); ~AudioChannel(); Logical TestInstance() const; // //-------------------------------------------------------------------- // Accessors //-------------------------------------------------------------------- // AudioChannelType GetAudioChannelType() { return audioChannelType; } MIDIChannel GetChannelNumber() { return midiChannel; } void SetVoicesUsed(AudioVoiceCount voices_used) { voicesUsed = voices_used; } AudioVoiceCount GetVoicesUsed() { return voicesUsed; } // //-------------------------------------------------------------------- // MIDI methods //-------------------------------------------------------------------- // void SendNoteOn(MIDIValue key, MIDIValue velocity); MIDIValue myPreset; MIDIValue myBank; void SendNoteOff(MIDIValue key, MIDIValue velocity); void SendProgramChange(MIDIValue program); void SendController(MIDIValue controller, MIDIValue value); void SendPolyKeyPressure(MIDIValue key, MIDIValue value); void SendChannelPressure(MIDIValue value); void SendPitchBend(MIDIPitchBend pitch_bend); void SendPitchBendRange(MIDIValue sensitivity); void SendNRPN(MIDIValue paramNumber, MIDINRPNValue value); void SelectEffect(MIDIEffectType type, MIDIValue effect); void SelectBank(MIDIValue bank); // //-------------------------------------------------------------------- // Release //-------------------------------------------------------------------- // void Release(); private: // //-------------------------------------------------------------------- // Private data //-------------------------------------------------------------------- // AudioChannelType audioChannelType; MIDIChannel midiChannel; AudioVoiceCount voicesUsed; AudioCard *audioCard; };*/ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioCard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /*class AudioCard : public Node { friend class AudioHardware; public: // //-------------------------------------------------------------------- // Constructor, Destructor, Testing //-------------------------------------------------------------------- // AudioCard(); ~AudioCard(); Logical TestInstance() const; // //-------------------------------------------------------------------- // Public methods //-------------------------------------------------------------------- // void Initialize(); void Close(); void GetEnvironmentSettings(char *env_str); Logical InitMIDIReceive(); void CloseMIDIReceive(); Logical IsMIDIAvailable(); MIDIValue GetMIDIByte(); void InitializeChannels(); int LoadSBK(const char *file_name); void ReleaseAllBanks(); // //-------------------------------------------------------------------- // MIDI methods //-------------------------------------------------------------------- // void SendNoteOn(MIDIChannel channel, MIDIValue key, MIDIValue velocity); void SendNoteOff(MIDIChannel channel, MIDIValue key, MIDIValue velocity); void SendProgramChange(MIDIChannel channel, MIDIValue program); void SendController(MIDIChannel channel, MIDIValue controller, MIDIValue value); void SendPolyKeyPressure(MIDIChannel channel, MIDIValue key, MIDIValue value); void SendChannelPressure(MIDIChannel channel, MIDIValue value); void SendPitchBendRange(MIDIChannel channel, MIDIValue sensitivity); void SendPitchBend(MIDIChannel channel, MIDIPitchBend pitch_bend); void SendSysex(void *data, size_t length); void SendNRPN(MIDIChannel channel, MIDIValue paramNumber, MIDINRPNValue value); void SelectEffect(MIDIEffectType type, MIDIValue effect); void SelectBank(MIDIChannel channel, MIDIValue bank); void SendMIDIMessage(MIDIMessage *midi_message, Word length); // //-------------------------------------------------------------------- // Channel methods //-------------------------------------------------------------------- // AudioChannel* RequestAudioChannel(AudioVoiceCount voice_count); void ReleaseAudioChannel(AudioChannel *audio_channel); private: // //-------------------------------------------------------------------- // Private methods //-------------------------------------------------------------------- // WORD GetHexWord(const char ** s); // //-------------------------------------------------------------------- // Private data //-------------------------------------------------------------------- // // // Card addresses // WORD srcAddx; WORD irqInterrupt; WORD dmaChannel; WORD mpuAddx; WORD emuAddx; // // Structure for the MIDI driver initialization function // Structure for the MIDI driver hardware // #ifdef AUDIO_HARDWARE _SOS_MIDI_INIT_DRIVER sSOSMIDIInitDriver; _SOS_MIDI_HARDWARE sSOSMIDIHardware; #endif // // Handle for the loaded MIDI driver // WORD wDriverHandle; // // Number of free voices // AudioVoiceCount idleVoices; // // Idle channels // ChainOf idleChannelSocket; ChainOf percussionChannelSocket; };*/ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHardware ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /*class AudioHardware : public Node { public: // //-------------------------------------------------------------------- // Constructor, Destructor, Testing //-------------------------------------------------------------------- // AudioHardware(); ~AudioHardware(); Logical TestInstance() const; static Logical TestClass(); static Logical ProfileClass(); // //-------------------------------------------------------------------- // Public methods //-------------------------------------------------------------------- // void Initialize(); void Close(); // //-------------------------------------------------------------------- // Card Access //-------------------------------------------------------------------- // AudioCard* GetFrontCard(); AudioCard* GetRearCard(); private: // //-------------------------------------------------------------------- // Private methods //-------------------------------------------------------------------- // // //-------------------------------------------------------------------- // Private data //-------------------------------------------------------------------- // AudioCard frontCard; AudioCard rearCard; };*/ //~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioCard inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /*inline void AudioCard::SendMIDIMessage(MIDIMessage *midi_message, Word length) { #ifdef AUDIO_HARDWARE SET_AUDIO_RENDERER_MIDI(); Check_Signature(midi_message); #if DEBUG_LEVEL>0 switch (midi_message->message[0] >> 4) { case MIDI_NOTE_ON_STATUS: case MIDI_NOTE_OFF_STATUS: case MIDI_POLYKEY_STATUS: case MIDI_CONTROLLER_STATUS: case MIDI_PITCH_BEND_STATUS: Verify(length == 3); break; case MIDI_PROGRAM_CHANGE_STATUS: case MIDI_CHANNEL_PRESSURE_STATUS: Verify(length == 2); break; default: Fail("Should never reach here"); break; } #endif #if DEBUG_LEVEL>0 { Word wError = sosMIDISendMIDIData(wDriverHandle, (char*)midi_message->message, length); Verify(wError == _ERR_NO_ERROR); } #else sosMIDISendMIDIData(wDriverHandle, (char*)midi_message->message, length); #endif CLEAR_AUDIO_RENDERER_MIDI(); #endif } // //-------------------------------------------------------------------- // MIDI methods //-------------------------------------------------------------------- // inline void AudioCard::SendNoteOn(MIDIChannel channel, MIDIValue key, MIDIValue velocity) { MIDIMessage message(MIDI_NOTE_ON_STATUS, channel, key, velocity); SendMIDIMessage(&message, 3); } inline void AudioCard::SendNoteOff(MIDIChannel channel, MIDIValue key, MIDIValue velocity) { MIDIMessage message(MIDI_NOTE_OFF_STATUS, channel, key, velocity); SendMIDIMessage(&message, 3); } inline void AudioCard::SendProgramChange(MIDIChannel channel, MIDIValue program) { MIDIMessage message(MIDI_PROGRAM_CHANGE_STATUS, channel, program); SendMIDIMessage(&message, 2); } inline void AudioCard::SendController(MIDIChannel channel, MIDIValue controller, MIDIValue value) { MIDIMessage message(MIDI_CONTROLLER_STATUS, channel, controller, value); SendMIDIMessage(&message, 3); } inline void AudioCard::SendPolyKeyPressure(MIDIChannel channel, MIDIValue key, MIDIValue value) { MIDIMessage message(MIDI_POLYKEY_STATUS, channel, key, value); SendMIDIMessage(&message, 3); } inline void AudioCard::SendChannelPressure(MIDIChannel channel, MIDIValue value) { MIDIMessage message(MIDI_CHANNEL_PRESSURE_STATUS, channel, value); SendMIDIMessage(&message, 2); } inline void AudioCard::SelectBank(MIDIChannel channel, MIDIValue bank) { SendController(channel, (MIDIValue)0, bank); } //~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioChannel inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ // //-------------------------------------------------------------------- // MIDI methods //-------------------------------------------------------------------- // inline void AudioChannel::SendNoteOn(MIDIValue key, MIDIValue velocity) { DEBUG_STREAM << "Sending note " << (int)key << " for bank " << (int)myBank << ", preset " << (int)myPreset << "." << std::endl << std::flush; //Check(audioCard); //audioCard->SendNoteOn(midiChannel,key,velocity); } inline void AudioChannel::SendNoteOff(MIDIValue key, MIDIValue velocity) { Check(audioCard); audioCard->SendNoteOff(midiChannel,key,velocity); } inline void AudioChannel::SendProgramChange(MIDIValue program) { Check(audioCard); myPreset = program; audioCard->SendProgramChange(midiChannel,program); } inline void AudioChannel::SendController(MIDIValue controller, MIDIValue value) { Check(audioCard); audioCard->SendController(midiChannel,controller,value); } inline void AudioChannel::SendPolyKeyPressure(MIDIValue key, MIDIValue value) { Check(audioCard); audioCard->SendPolyKeyPressure(midiChannel,key,value); } inline void AudioChannel::SendChannelPressure(MIDIValue value) { Check(audioCard); audioCard->SendChannelPressure(midiChannel,value); } inline void AudioChannel::SendPitchBend(MIDIPitchBend pitch_bend) { Check(audioCard); audioCard->SendPitchBend(midiChannel,pitch_bend); } inline void AudioChannel::SendPitchBendRange(MIDIValue sensitivity) { Check(audioCard); audioCard->SendPitchBendRange(midiChannel,sensitivity); } inline void AudioChannel::SelectEffect(MIDIEffectType type, MIDIValue effect) { Check(audioCard); audioCard->SelectEffect(type,effect); } inline void AudioChannel::SendNRPN(MIDIValue paramNumber, MIDINRPNValue value) { Check(audioCard); audioCard->SendNRPN(midiChannel,paramNumber,value); } inline void AudioChannel::SelectBank(MIDIValue bank) { Check(audioCard); myBank = bank; audioCard->SelectBank(midiChannel,bank); } inline void AudioChannel::Release() { Check(audioCard); audioCard->ReleaseAudioChannel(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHardware inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ inline AudioCard* AudioHardware::GetFrontCard() { Check(this); return &frontCard; } inline AudioCard* AudioHardware::GetRearCard() { Check(this); return &rearCard; }*/