Multi-threaded Mandelbulbs

Visions Of Chaos now supports multithreaded rendering for Mandelbulbs, Mandelbox and Kaleidoscopic IFS rendering. 2x speedup for dual core CPUs. 8x speedup for the new i7 8 core CPUs.

I had never done multiple threaded code in Delphi before and found it difficult to get the right info from googling tips/hints etc. So here are a few tips of my own for someone trying to write multi-threaded code in Delphi.

1. When converting a non threaded bit of code into threaded, make sure the thread has all needed variables within the thread itself. Minimize accessing global variables as much as possible.

2. When you do need to access (read or write) a global variable or the main form or any dialog, forget using Synchronize. I found it tedious to implement and slower than using critical sections. To use critical sections;

Create a global variable
var criticalsection:TRTLCriticalSection;

Before you start/spawn the threads, define the critical section
InitializeCriticalSection(CriticalSection);

Now, during any part of the threaded code that needs to access a global variable or the main form, surround the code as follows
EnterCriticalSection(CriticalSection);

LeaveCriticalSection(CriticalSection);

After all threads have finished, remove the critical section
DeleteCriticalSection(CriticalSection);

Using critical sections is much easier than setting up separate procedures within your thread that are called with synchronize, and I found the performance and speed was faster with critical sections.

3. If you set the priority of created threads, make sure the priority is the same or lower than the main application priority. If this is not done then the main form will be less responsive and/or the threads will not be as responsive when running.

Hopefully that helps someone else getting to grips with threads in Delphi. Once you get the basics down threads are not that complicated.

Jason.

Controlling MIDI Output with Delphi

I found it difficult when I first started trying MIDI programming to get any decent documentation or a simple snippet of code to turn MIDI notes on and off. This Delphi source code allows you to control the Windows MIDI notes from within a Delphi application. Create a new unit _midi.pas and copy and paste the code contents below into it.

This allows single or multiple notes to be played. Using these simple commands (all based on the mmsystem.pas unit that talks to the windows MMSYSTEM.DLL) is how I handled all the MIDI in GBK.

Hopefully this helps anyone who is looking for a simple way to get MIDI support into their Delphi application.


{
Instructions:
1) Call OpenMidiOut before playing any notes
2) Call TurnOnMidiNote to start playing a note
   This can be called multiple times for "simultaneous" notes
3) Add some sort of delay for the notes. ie sleep() etc
4) Call TurnOffMidiNote to stop playing all playing note(s)
5) When done, call CloseMidiOut to allow other apps to access the midi port
}

unit _midi;

interface

uses Windows,Messages,SysUtils,Classes,Graphics,Controls,
     Forms,Dialogs,StdCtrls,mmsystem,registry;

function MidiAvailable:boolean;
procedure OpenMidiOut(ParentForm:TForm);
procedure TurnOnMidiNote(Note,Instrument,Volume,Channel,Panning:byte);
procedure TurnOffSingleMidiNote(Note,Channel:byte);
procedure TurnOffAllMidiNotes;
procedure CloseMidiOut;

var MidiOutDev:HMIDIOUT; //global handle to midi device
    MidiOpen:boolean; //refer to this variable to see if a midi device is currently open

implementation

function MidiAvailable:boolean;
begin
     If (midiOutGetNumDevs()=0) then MidiAvailable:=false
     else MidiAvailable:=true;
end;

procedure OpenMidiOut(ParentForm:TForm);
begin
     midiOutOpen(@MidiOutDev,MIDI_MAPPER,ParentForm.Handle,0,CALLBACK_WINDOW);
     MidiOpen:=true;
end;

//note = 0-127 - see table at bottom for values
//inst = 0-127 - see table at bottom for values
//vol  = 0-127
//chan = 0-15
//pan  = 0-127 0=only left 63=both 127=only right
procedure TurnOnMidiNote(Note,Instrument,Volume,Channel,Panning:byte);
begin
     //tell midi device which instrument or patch to use
     midiOutShortMsg(MidiOutDev,MAKEWORD($C0 OR Channel,Instrument));

     //panning
     midiOutShortMsg(midioutdev,strtoint('$'+inttohex(panning,2)+'0AB'+inttohex(channel,1)));

     //tell midi device what note to play
     midiOutShortMsg(MidiOutDev,MAKELONG(MAKEWORD($90 or Channel,Note),MAKEWORD(Volume,0)));
end;

procedure TurnOffSingleMidiNote(Note,Channel:byte);
begin
     //tell midi device what note to play
     midiOutShortMsg(MidiOutDev,MAKELONG(MAKEWORD($80 or Channel,Note),MAKEWORD(0,0)));
end;

procedure TurnOffAllMidiNotes;
begin
     {Reset the midi device}
     midiOutReset(MidiOutDev);
end;

procedure CloseMidiOut;
begin
     {Close the midi device so anyone else can use it.}
     midiOutClose(MidiOutDev);
     MidiOpen:=false;
end;

{
Oct#  C   C#  D   D#  E   F   F#  G   G#  A   A#  B
 -1   0   1   2   3   4   5   6   7   8   9   10  11
  0   12  13  14  15  16  17  18  19  20  21  22  23
  1   24  25  26  27  28  29  30  31  32  33  34  35
  2   36  37  38  39  40  41  42  43  44  45  46  47
  3   48  49  50  51  52  53  54  55  56  57  58  59
  4   60  61  62  63  64  65  66  67  68  69  70  71
  5   72  73  74  75  76  77  78  79  80  81  82  83
  6   84  85  86  87  88  89  90  91  92  93  94  95
  7   96  97  98  99  100 101 102 103 104 105 106 107
  8   108 109 110 111 112 113 114 115 116 117 118 119
  9   120 121 122 123 124 125 126 127
}

{
Acoustic Grand Piano
Bright Acoustic Piano
Electric Grand Piano
Honky-tonk Piano
Electric Piano 1
Electric Piano 2
Harpsichord
Clavi
Celesta
Glockenspiel
Music Box
Vibraphone
Marimba
Xylophone
Tubular Bells
Dulcimer
Drawbar Organ
Percussive Organ
Rock Organ
Church Organ
Reed Organ
Accordion
Harmonica
Tango Accordion
Acoustic Guitar (nylon)
Acoustic Guitar (steel)
Electric Guitar (jazz)
Electric Guitar (clean)
Electric Guitar (muted)
Overdriven Guitar
Distortion Guitar
Guitar harmonics
Acoustic Bass
Electric Bass (finger)
Electric Bass (pick)
Fretless Bass
Slap Bass 1
Slap Bass 2
Synth Bass 1
Synth Bass 2
Violin
Viola
Cello
Contrabass
Tremolo Strings
Pizzicato Strings
Orchestral Harp
Timpani
String Ensemble 1
String Ensemble 2
SynthStrings 1
SynthStrings 2
Choir Aahs
Voice Oohs
Synth Voice
Orchestra Hit
Trumpet
Trombone
Tuba
Muted Trumpet
French Horn
Brass Section
SynthBrass 1
SynthBrass 2
Soprano Sax
Alto Sax
Tenor Sax
Baritone Sax
Oboe
English Horn
Bassoon
Clarinet
Piccolo
Flute
Recorder
Pan Flute
Blown Bottle
Shakuhachi
Whistle
Ocarina
Lead 1 (square)
Lead 2 (sawtooth)
Lead 3 (calliope)
Lead 4 (chiff)
Lead 5 (charang)
Lead 6 (voice)
Lead 7 (fifths)
Lead 8 (bass + lead)
Pad 1 (new age)
Pad 2 (warm)
Pad 3 (polysynth)
Pad 4 (choir)
Pad 5 (bowed)
Pad 6 (metallic)
Pad 7 (halo)
Pad 8 (sweep)
FX 1 (rain)
FX 2 (soundtrack)
FX 3 (crystal)
FX 4 (atmosphere)
FX 5 (brightness)
FX 6 (goblins)
FX 7 (echoes)
FX 8 (sci-fi)
Sitar
Banjo
Shamisen
Koto
Kalimba
Bag pipe
Fiddle
Shanai
Tinkle Bell
Agogo
Steel Drums
Woodblock
Taiko Drum
Melodic Tom
Synth Drum
Reverse Cymbal
Guitar Fret Noise
Breath Noise
Seashore
Bird Tweet
Telephone Ring
Helicopter
Applause
Gunshot
}

end.

I have been using Delphi for years for programming all the applications on Softology. I highly recommend it to anyone interested in programming. If they would only release a cheap/free entry level version for newcomers to play with.

Jason.