// Example_aud.cpp
// Sample code explaining how to use the CDirectMidi class library (Audio part)
// Last update April 27th, 2004
// Programmed by Carlos Jim�nez de Parga
// Feel free to modify this code
// Your comments and suggestions are always welcomed
// Main headers
// ANSI I/0 headers
#include <conio.h>
#include <iostream>
#include <math.h>
// The class wrapper
#include ".\\DirectMidi\\CDirectMidi.h"
// Inline library inclusion
#pragma comment (lib,"dxguid.lib") // guid definitions
#pragma comment (lib,"winmm.lib")
#pragma comment (lib,"dsound.lib")
#pragma comment (lib,"dxerr9.lib")
using namespace std;
using namespace directmidi;
int main(int argc, char* argv[])
{
CDirectMusic CDMusic;
CDLSLoader CLoader;
COutputPort COutPort,COutPort2;
CInputPort CInPort;
CPortPerformance CPortPerformance;
CAPathPerformance CAPathPerformance;
CCollection CCollectionA;
CInstrument CInstrument1;
CAudioPath CAudioPath1;
CSegment CSegment1;
C3DSegment C3DSegment1;
C3DBuffer C3DBuffer1;
try
{
/////////////////////////////// INITIALIZATION //////////////////////////
// Initializes DirectMusic
CDMusic.Initialize();
// Initializes an audiopath performance
CAPathPerformance.Initialize(CDMusic,NULL,NULL,DMUS_APATH_DYNAMIC_3D,128);
// Initializes a port performance object
CPortPerformance.Initialize(CDMusic,NULL,NULL);
// Initializes loader object
CLoader.Initialize();
// Initializes output port
COutPort.Initialize(CDMusic);
// Selects the first software synthesizer port
INFOPORT PortInfo;
DWORD dwPortCount = 0;
do
COutPort.GetPortInfo(++dwPortCount,&PortInfo);
while (!(PortInfo.dwFlags & DMUS_PC_SOFTWARESYNTH));
cout << "Selected output port: " << PortInfo.szPortDescription << endl;
COutPort.SetPortParams(0,0,0,SET_REVERB | SET_CHORUS,44100);
COutPort.ActivatePort(&PortInfo);
////////////////////////////////// PLAYING A SEGMENT ////////////////////////////
// Adds the selected port to the performance
CPortPerformance.AddPort(COutPort,0,1);
// Loads a MIDI file into the segment
CLoader.LoadSegment(_T(".\\media\\laststar.mid"),CSegment1,TRUE);
// Repeats the segment until infinite
CSegment1.SetRepeats(DMUS_SEG_REPEAT_INFINITE);
// Downloads the segment to the performance
CSegment1.Download(CPortPerformance);
// Plays the segment
CPortPerformance.PlaySegment(CSegment1);
cout << "Playing a segment with the port performance. Press a key to continue...\n" << endl;
getch();
//////////////////////////////// CHANGING TEMPO //////////////////////////////
cout << "Changing tempo to 1/2. Press a key to continue...\n" << endl;
CPortPerformance.SetMasterTempo(0.5);
getch();
cout << "Changing tempo to 2x. Press a key to continue...\n" << endl;
CPortPerformance.SetMasterTempo(2.0);
getch();
CPortPerformance.SetMasterTempo(1.0);
/////////////////////////////// CHANGING VOLUME ////////////////////////////
cout << "Changing volume" << endl;
for (long lV = 0;lV >= -4000;lV-=4)
{
CPortPerformance.SetMasterVolume(lV);
Sleep(1);
}
for (lV = -4000;lV <= 0;lV+=4)
{
CPortPerformance.SetMasterVolume(lV);
Sleep(1);
}
cout << "Press a key to continue..." << endl;
getch();
////////////////////////// PLAYING A NOTE WITH A PORT PERFORMANCE /////////////////
// Stops the playing segment
CPortPerformance.Stop(CSegment1);
// Sends a note-on to the port performance
CPortPerformance.SendMidiMsg(NOTE_ON,64,127,1);
cout << "Sending a MIDI note-on to the port performance on PChannel 1. Press a key to continue...\n" << endl;
getch();
CPortPerformance.SendMidiMsg(NOTE_OFF,64,127,1);
////////////// PLAYING A SEGMENT WITH AN AUDIOPATH PERFORMANCE IN 3D ////////////
// Downloads the segment to the audio path performance
CSegment1.Download(CAPathPerformance);
// Plays the segment in the performance
CAPathPerformance.PlaySegment(CSegment1,NULL);
cout << "Playing a segment with the audio path performance. Press a key to continue...\n" << endl;
getch();
// Stops the current playing segment
CAPathPerformance.Stop(CSegment1);
C3DSegment1.Initialize(CAPathPerformance);
// Clones the normal segment to a 3D segment
C3DSegment1 = CSegment1;
// Plays the 3D segment in the audiopath performance
CAPathPerformance.PlaySegment(C3DSegment1);
// Positions the 3D buffer one unit in the negative X-axis
C3DSegment1.SetBufferPosition(-1.0,0.0,0.0);
cout << "Playing a 3D segment on your left. Press a key to continue...\n" << endl;
getch();
// Positions the 3D buffer one unit in the positive X-axis
C3DSegment1.SetBufferPosition(1.0,0.0,0.0);
cout << "Playing a 3D segment on your right. Press a key to continue...\n" << endl;
getch();
////////////////////////////// PLAYING A NOTE IN 3D ////////////////////////
// Stops the playing 3D segment
CAPathPerformance.Stop(C3DSegment1);
// Sets the buffer position
C3DSegment1.SetBufferPosition(-1.0,0.0,0.0);
// Sends a note-on with the 3D segment audiopath configuration
CAPathPerformance.SendMidiMsg(NOTE_ON,64,127,0,C3DSegment1.GetAudioPath());
cout << "Playing a MIDI note-on with the audio path performance on your left. Press a key to continue...\n" << endl;
getch();
CAPathPerformance.SendMidiMsg(NOTE_OFF,64,127,0,C3DSegment1.GetAudioPath());
///////////////////////////// PLAYING A DLS INSTRUMENT IN 3D /////////////////////
// Gets the defult audiopath for the performance
CAPathPerformance.GetDefaultAudioPath(CAudioPath1);
// Gets a 3D buffer
CAudioPath1.Get3DBuffer(C3DBuffer1);
// Positions the 3D buffer one unit in the negative X-axis
C3DBuffer1.SetBufferPosition(-1.0,0.0,0.0);
// Unloads the segment from the audio path performance
CSegment1.Unload(CAPathPerformance);
// Loads the default GM/GS collection
CLoader.LoadDLS(NULL,CCollectionA);
// Gets the instrument 215
CCollectionA.GetInstrument(CInstrument1,215);
// Assigns the patch 0
CInstrument1.SetPatch(0);
// Set up the note range
CInstrument1.SetNoteRange(0,127);
DWORD dwGroup,dwMChannel;
// Downloads the instrument to the performance channel 1
CAPathPerformance.DownloadInstrument(CInstrument1,1,&dwGroup,&dwMChannel);
// Selects the patch and plays the note on PChannel 1
CAPathPerformance.SendMidiMsg(PATCH_CHANGE,0,0,1,CAudioPath1);
CAPathPerformance.SendMidiMsg(NOTE_ON,64,127,1,CAudioPath1);
cout << "Playing a GM/GS DLS instrument with the audio performance on your left. Press a key to coninue...\n" << endl;
getch();
///////////////////////// PLAYING A SAMPLE INSTRUMENT IN 3D ///////////////
CAPathPerformance.SendMidiMsg(NOTE_OFF,64,0,1,CAudioPath1);
// Unloads the instrument from the audiopath
CAPathPerformance.UnloadInstrument(CInstrument1);
// Gets the port where the performance channel 2 resides
IDirectMusicPort8* pPort = NULL;
CAPathPerformance.PChannelInfo(2,&pPort,NULL,NULL);
// Initializes output port
COutPort2.Initialize(CDMusic);
// Activates ouput port from the interface
COutPort2.ActivatePortFromInterface(pPort);
CSampleInstrument CSample1;
// Loads the .wav file
CDLSLoader::LoadWaveFile(_T(".\\media\\starbreeze.wav"),CSample1,DM_USE_MEMORY);
// Assigns the patch
CSample1.SetPatch(2);
// Sets a continuous wave loop
CSample1.SetLoop(TRUE);
// Set additional wave parameters
CSample1.SetWaveParams(0,0,68,F_WSMP_NO_TRUNCATION);
REGION region;
ARTICPARAMS articparams;
// Initializes structures
ZeroMemory(®ion,sizeof(REGION));
ZeroMemory(&articparams,sizeof(ARTICPARAMS));
// Sets the region parameters
region.RangeKey.usHigh = 127;
region.RangeKey.usLow = 0;
region.RangeVelocity.usHigh = 127;
// Adjust LFO
articparams.LFO.tcDelay = TimeCents(10.0);
articparams.LFO.pcFrequency = PitchCents(5.0);
// Sets the pitch envelope
articparams.PitchEG.tcAttack = TimeCents(0.0);
articparams.PitchEG.tcDecay = TimeCents(0.0);
articparams.PitchEG.ptSustain = PercentUnits(0.0);
articparams.PitchEG.tcRelease = TimeCents(0.0);
// Sets the volume envelope
articparams.VolEG.tcAttack = TimeCents(1.275);
articparams.VolEG.tcDecay = TimeCents(0.0);
articparams.VolEG.ptSustain = PercentUnits(100.0);
articparams.VolEG.tcRelease = TimeCents(10.157);
// Sets the instrument parameters
CSample1.SetRegion(®ion);
CSample1.SetArticulationParams(&articparams);
// Allocate interface memory
COutPort2.AllocateMemory(CSample1);
// Download the sample instrument to the port
COutPort2.DownloadInstrument(CSample1);
// Positions the buffer
C3DBuffer1.SetBufferPosition(1.0,0.0,0.0);
// Selects patch and plays the note
CAPathPerformance.SendMidiMsg(PATCH_CHANGE,2,0,2,CAudioPath1);
CAPathPerformance.SendMidiMsg(NOTE_ON,64,127,2,CAudioPath1);
cout << "Playing a downloaded WAV file with the audio path performance on the right. Press a key to continue... \n" << endl;
getch();
///////////// PLAYING A 3D SAMPLE INSTRUMENT WITH AN EXTERNAL KEYBOARD ///////////
CAPathPerformance.SendMidiMsg(NOTE_OFF,64,127,2,CAudioPath1);
// Initializes and activates default input MIDI port
CInPort.Initialize(CDMusic);
CInPort.GetPortInfo(1,&PortInfo);
CInPort.ActivatePort(&PortInfo);
// Finds out which group and MIDI channel are assigned to PChannel 2
CAPathPerformance.PChannelInfo(2,NULL,&dwGroup,&dwMChannel);
// Activates the thru over the retrieved MIDI channel and group
CInPort.SetThru(0,dwGroup,dwMChannel,COutPort2);
cout << "Activating MIDI thru from input MIDI channel 0 to PChannel 2.\n" \
"Play with an external keyboard. Press a key to continue... \n" << endl;
getch();
//////////////////////// RETRIEVING A STANDARD DMO OBJECT ///////////////////
// Releases the old audiopath handler
CAudioPath1.ReleaseAudioPath();
CAPathPerformance.RemoveDefaultAudioPath();
// Creates a new audiopath
CAPathPerformance.CreateAudioPath(CAudioPath1,DMUS_APATH_SHARED_STEREOPLUSREVERB,64,TRUE);
// Declares a DMO interface pointer
CComPtr<IDirectSoundFXWavesReverb8> pEffectDMO;
// Gets the DMO
CAudioPath1.GetObjectInPath(DMUS_PCHANNEL_ALL,DMUS_PATH_BUFFER_DMO,
1,GUID_All_Objects,0,IID_IDirectSoundFXWavesReverb8,(void**)&pEffectDMO);
// Maximum reverberation
DSFXWavesReverb FX;
FX.fInGain = DSFX_WAVESREVERB_INGAIN_MAX;
FX.fReverbMix = DSFX_WAVESREVERB_REVERBMIX_MAX;
FX.fReverbTime = DSFX_WAVESREVERB_REVERBTIME_MAX;
FX.fHighFreqRTRatio = DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX;
pEffectDMO->SetAllParameters(&FX);
cout << "Playing a sample on PChannel 2 with maximum reverberation.\n" \
"Play with an external keyboard. Press a key to end the application...\n" << endl;
getch();
}
catch (CDMusicException& DMExcp)
{
cout << "\n" << DMExcp.GetErrorDescription() << "\n" << endl;
}
return 0;
}