Playing polyphonic music by using separate circuitry for each "voice" works very nicely when music is logically subdivided into a number of single-voice channels. In many cases, one not only won't care if the hardware voices aren't perfectly matched--one may even want to have some of them be a little louder than others.
When using a polyphonic instrument to play MIDI data, however, it's important to ensure that all voices behave equivalently, and the easiest way to accomplish that is to use the same circuitry to implement all of them, typically with some sort of wave-table generation.
There are many ways to perform wave-table-based music, which trade off sophistication for CPU time and memory requirements. I've written a four-voice wave-table generator for the 6502 which used twelve instructions (46 cycles) for each output sample [an average of only three per voice!] but it required almost 3K worth of data tables. I've also written an 8-voice wave-table generator for a 10MHz PIC and a 16-voice one for the PSOC. I've not done much with the Arduino, but I would guess an eight-voice wave-table synth would be workable.
There's an important thing to note, however, when doing a wave-table synth: square waves often sound bad if timing is quantized to something that isn't a multiple of their frequency. If you wish to generate clean square waves for a five-octave MIDI keyboard, you may need to use a rather high sampling rate. If you want to generate smoother waves instead you can get by with a lower sampling rate.
I've not used the Arduino, so I don't know what sorts of constructs in C would yield the best code, but a typical wave-table implementation on the ARM would look like:
uint32_t freq[8],phase[8];
int32_t volume[8];
int8_t *table[8]; // Pointer to 256-byte array
int32_t total;
total = 0;
phase[0] += freq[0]; total += table[0][phase[0] >> 8]*volume[0];
phase[1] += freq[1]; total += table[1][phase[1] >> 8]*volume[1];
...
phase[7] += freq[7]; total += table[7][phase[7] >> 8]*volume[7];
After the above code, total
will hold a value which may be scaled (if needed) and either output to a DAC or used to set a PWM duty cycle.
The above code assumes that the wave table is exactly 256 bytes long; other approaches can be used if that isn't the case. If the Arduino can't efficiently perform the multiplication by volume
, it's possible to use a different table for each volume level (my 6502 code used two sets of tables--one for "loud" and one for "soft").
An additional consideration if you're using a DAC (less applicable if you're using a PWM) is that rather than summing together all the individual values generated for each wave and outputting them as a group, it may be helpful have an interrupt which happens eight times as fast, and outputs the value for one wave each time. Doing that will effectively gain three more bits of ADC precision. Also, if you happen to want sine waves and your hardware doesn't support fast multiplication, generating two full-amplitude sine waves whose frequencies match but whose phases differ, is equivalent to generating one sine wave whose phase is the average of the two full-strength ones, and whose amplitude is proportional to the quantity "one plus the cosine of the phase difference". My PIC-based waveform generator used that trick.
Probably you don't know/understand what isolation means when dealing with optocouplers/optoisolators.
It doesn't mean that there is some sort of circuit buffering separating the two circuits. It really means electrical isolation, i.e. there is no current flowing from one part to the other (an optocoupler does that).
An optocoupler is essentially an LED and a photodiode (or a phototransistor) optically coupled in the same package. The LED and the photodiode don't share any electrical connection. They only "communicate" through the light generated by the LED. Therefore the "input section" (the LED) can be driven by a circuit which is completely isolated from the circuit connected to the "output section" (the photodiode/phototransistor).
This allows two circuits that must remain electrically isolated to communicate.
So the answer is no, an NE555 cannot substitute a circuit which performs electrical isolation.
If you're desperate or don't need specific performance/reliability you could try building a poor man's optocoupler. And here is another attempt.
Important Note: if your circuit needs an optocoupler for stringent safety reasons, using one of those home made one could pose some serious safety risks, so be warned!
That is, I wouldn't trust a mains-powered heart-beat detector using a home-made optocoupler to be used on my chest!!!
Best Answer
I'd suggest the best device selections are the 6n137 or in a slightly smaller physical form the H11L1 where you can save two pins worth of board space.
The reason these are ideal is that they are digital devices (they have a Schmidt level gate driver) rather than the analog devices such as the 6N138/139 or even the SFH6916 suggested in the comments.
The speed of your MIDI command is very low (31k baud) so this is not a concern. However you need to ensure you have what's called hysteresis built into the signal path so you get clean replication of the signals passing through your MIDI devices. The digital parts give you this built in, whereas with the analog parts you have to design this in which typically requires more components for through signals.
Here's the relationship between input current and the digital output for the H11L1:
You can see here that the current requirement to switch state of the digital output is just under 1 mA (you don't have to deal with current transfer ratios with digital devices) and the hysteresis is built in.
You MIDI interface will switch between 0 mA and about 5.5 mA (if you use the 3 220 Ohm resistors recommended) for it's low/high state. The reverse protection diode shown in many schematics is a good idea, just for safety.