The result of the algorithm, described below, is here
I have an array of notes: { 60, 63, 67, 70, 73, 77, 73, 70, 67, 63 }
and a NOTE_LENGTH
variable
I start with sending the first to a MidiOutput device with a standard MIDI tenor saxophone.
When the last note is played for 2/3 of NOTE_LENGTH
milliseconds, I send the next one. When a note is played for NOTE_LENGTH
, I stop it.
Notes are started with Midi NoteOn
and stopped wit Midi NoteOff
It's easy to find where a note starts in the resulting audio. It is not smooth, while a real saxophone is. How do I achieve a smooth transition like in this video? I'm not a musician, so I don't know, what a technical difference is.
UPDATE
Source code, C# + NAudio.dll 1.3.8.0 (Note, that it may not work in later versions of dll)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NAudio.Midi;
namespace Sax
{
class Program
{
static void Main(string[] args)
{
MidiOut midi_out = new MidiOut(0);
midi_out.Volume = 65535;
midi_out.Send(MidiMessage.ChangePatch(67, 0).RawData);
midi_out.Send(MidiMessage.ChangePatch(67, 1).RawData);
int iteration = 0;
int[] notes = new int[] { 60, 63, 67, 70, 73, 77, 73, 70, 67, 63 };
//int[] notes = new int[] { 60, 61, 62, 63, 64, 65, 64, 63, 62, 61 };
const int NOTE_LENGTH = 729;
while (true)
{
midi_out.Send(MidiMessage.StartNote(notes[iteration % notes.Length], 127, iteration % 2).RawData);
Thread.Sleep(1 * NOTE_LENGTH / 3);
if (iteration != 0)
midi_out.Send(MidiMessage.StopNote(notes[(iteration - 1) % notes.Length], 127, (iteration - 1) % 2).RawData);
Thread.Sleep(1 * NOTE_LENGTH / 3);
midi_out.Send(MidiMessage.StartNote(notes[(iteration + 1) % notes.Length], 127, (iteration + 1) % 2).RawData);
Thread.Sleep(NOTE_LENGTH / 3);
midi_out.Send(MidiMessage.StopNote(notes[iteration % notes.Length], 127, iteration % 2).RawData);
Thread.Sleep(NOTE_LENGTH/3);
++iteration;
}
}
}
}