Hi everyone. Got another help post. One of my free software is a little piano player that uses MIDI notes as well as real piano samples in .ogg format. The user can click on each key to play the sample or use their keyboard or connect a midi keyboard to the pc and use it with the software. The point is there's multiple ways to activate the PlaySample code below. I don't notice any latency. But I have a reasonably powerful computer. I have a user say that he's experiencing 100ms or so of latency which is killing the enjoyment. I looked at my code and it all seems to be right and I can't figure out how to improve it. Can you take a look and let me know if there's an "aha!" moment of something i'm missing that could improve playback, possibly on lower end computers?
The piano samples are loaded into memory at runtime or if they change the base octave they're playing on. But they are NOT loaded every time a key is pressed.
Here's the relevant C# code:
using Un4seen.Bass;
using Un4seen.Bass.AddOn.Mix;
private readonly List<int> STREAMS;
private int BassMixer;
private int BassStream;
private const int BassBuffer = 100;
if (!Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Handle))
{
MessageBox.Show("Error initializing BASS.NET:\n" + Bass.BASS_ErrorGetCode() + "\nWon't be able to play any audio!", AppName, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER, BassBuffer);
Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 5);
private void LoadPianoSamples()
{
var SamplePath = Application.StartupPath + "\\samples\\";
var missing = new List<int>();
for (var i = 0; i < 25; i++)
{
var actualSample = (BaseOctave * 12) + i + 3; //we're always going from C1, first three samples can't be used
try
{
if (File.Exists(SamplePath + actualSample + ".ogg"))
{
STREAMS[i] = Bass.BASS_StreamCreateFile(SamplePath + actualSample + ".ogg", 0L, 0L, BASSFlag.BASS_SAMPLE_FLOAT);
}
else if (File.Exists(SamplePath + actualSample + ".wav"))
{
STREAMS[i] = Bass.BASS_StreamCreateFile(SamplePath + actualSample + ".wav", 0L, 0L, BASSFlag.BASS_SAMPLE_FLOAT);
}
else
{
missing.Add(actualSample);
STREAMS[i] = 0;
}
}
catch (Exception ex)
{
MessageBox.Show("Error loading sample: '" + actualSample + "':\n" + ex.Message + "\nSample will NOT play.", AppName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
if (!missing.Any()) return;
var samples = missing.Aggregate("", (current, t) => current + ("'" + t + "'\n"));
MessageBox.Show("The following " + (missing.Count > 1 ? "samples are" : "sample is") + " missing:\n" + samples + "You can use .ogg and .wav files only\nMissing " + (missing.Count > 1 ? "samples" : "sample") + " will NOT play.", AppName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
private void PlaySample(int key, int velocity)
{
const int PADDING = 12; //seems this player is an octave lower than our piano samples, let's compensate
var MIDI_NOTE = PADDING + key + (BaseOctave*12);
if (CurrentAudioType > 0)
{
MidiPlayer.Play(new NoteOn(0, 1, (byte)MIDI_NOTE, 127));
}
else
{
Bass.BASS_ChannelSetAttribute(STREAMS[key], BASSAttribute.BASS_ATTRIB_VOL, (float)(velocity / 127.0));
Bass.BASS_ChannelPlay(STREAMS[key], true);
}
STATE_INPUT[key] = true;
UpdatePressedKeys(key);
}
Thank you!