midiFileLoader.MPTK_DeltaTicksPerQuarterNote
MPTK_Load()
. If
you're already doing that, it means it hasn't finished loading yet. There's
a callback event I can't remember the exact name of right now because I'm not at
my computer but it's something along the lines of midiFilePlayer.OnMidiLoad
and you should call whatever you're doing from there. (edited)
midiFilePlayer.MPTK_TickCurrent = 500;
private void OnApplicationPause(bool pause)
{
//Debug.Log("MidiFilePlayer OnApplicationPause " + pause);
if (pause && MPTK_PauseOnFocusLoss)
watchMidi.Stop();
else if (!watchMidi.IsRunning)
watchMidi.Start();
}
void OnApplicationFocus(bool hasFocus)
{
//Debug.Log("MidiFilePlayer OnApplicationFocus " + hasFocus);
if (!hasFocus && MPTK_PauseOnFocusLoss)
watchMidi.Stop();
else if (!watchMidi.IsRunning)
watchMidi.Start();
}
I have Pause On Focus loss set but even though I have that checked, the code in the else
if (!watchMidi.IsRunning) blocks are still running, causing a few seconds of the midi
file to play ahead of my music track.
I believe you can replicate this issue by explicitly calling the pause function from
code, unfocusing the application window and refocusing it, which will cause the midi to
play even though it is supposed to remain paused. (edited)
private void OnApplicationPause(bool pause)
{
//Debug.Log("MidiFilePlayer OnApplicationPause " + pause);
if (pause && MPTK_PauseOnFocusLoss)
watchMidi.Stop();
else if (!watchMidi.IsRunning)
watchMidi.Start();
}
void OnApplicationFocus(bool hasFocus)
{
//Debug.Log("MidiFilePlayer OnApplicationFocus " + hasFocus);
if (!hasFocus && MPTK_PauseOnFocusLoss)
watchMidi.Stop();
else if (!watchMidi.IsRunning)
watchMidi.Start();
}
I have Pause On Focus loss set but even though I have that checked, the code in the
else if (!watchMidi.IsRunning) blocks are still running, causing a few seconds of
the midi file to play ahead of my music track.
I believe you can replicate this issue by explicitly calling the pause function from
code, unfocusing the application window and refocusing it, which will cause the midi
to play even though it is supposed to remain paused. (edited) public void MPTK_UnPause()
{
try
{
// add this line:
pauseWhenFocusLost = false;
if (MPTK_CorePlayer)
{
if (timeMidiFromStartPlay <= 0d) watchMidi.Reset(); // V2.82
watchMidi.Start();
playPause = false;
}
else
{
playPause = false;
}
}
catch (System.Exception ex)
{
MidiPlayerGlobal.ErrorDetail(ex);
}
}
(edited) void OnApplicationFocus(bool hasFocus)
{
Debug.Log("TestMidiStream OnApplicationFocus " + hasFocus);
if (!hasFocus)
{
midiStreamPlayer.MPTK_StopSynth();
midiStreamPlayer.CoreAudioSource.enabled = false;
}
else
{
midiStreamPlayer.MPTK_InitSynth();
midiStreamPlayer.CoreAudioSource.enabled = true;
}
}
midiFilePlayer.OnEventNotesMidi.AddListener(MidiReadEvents);
public void MidiReadEvents(List<MPTKEvent> midiEvents)
{
foreach (MPTKEvent midiEvent in midiEvents)
{
switch (midiEvent.Command)
{
case MPTKCommand.MetaEvent:
switch (midiEvent.Meta)
{
case MPTKMeta.SequenceTrackName:
infoSeqTrackName += $"Track:{midiEvent.Track:00} '{midiEvent.Info}'\n";
//Debug.LogFormat($"SequenceTrackName Track:{midiEvent.Track} {midiEvent.Value} Name:'{midiEvent.Info}'");
break;
}
break;
}
}
}
midiFilePlayer.OnEventNotesMidi.AddListener(MidiReadEvents);
public void MidiReadEvents(List<MPTKEvent> midiEvents)
{
foreach (MPTKEvent midiEvent in midiEvents)
{
switch (midiEvent.Command)
{
case MPTKCommand.MetaEvent:
switch (midiEvent.Meta)
{
case MPTKMeta.SequenceTrackName:
infoSeqTrackName += $"Track:{midiEvent.Track:00} '{midiEvent.Info}'\n";
//Debug.LogFormat($"SequenceTrackName Track:{midiEvent.Track} {midiEvent.Value} Name:'{midiEvent.Info}'");
break;
}
break;
}
}
}
SoundFont not yet loaded, Midi Event cannot be processed Code:NoteOn Channel:0
...
MidiPlayerTK.MidiStreamPlayer:MPTK_PlayEvent (MidiPlayerTK.MPTKEvent) (at .../MidiStreamPlayer.cs:148)
MPTK_ChannelBankGetIndex
returns -1 when in the error state. Re-running MPTK_InitSynth
doesn't fix the sound, although MPTK_ChannelBankGetIndex
returns 0 after running it.
I'm not familiar with SoundFonts, how do I reload it and perhaps what causes it to
unload? (edited)SoundFont not yet loaded, Midi Event cannot be processed Code:NoteOn Channel:0
...
MidiPlayerTK.MidiStreamPlayer:MPTK_PlayEvent (MidiPlayerTK.MPTKEvent) (at .../MidiStreamPlayer.cs:148)
MPTK_ChannelBankGetIndex
returns -1 when in the error state. Re-running MPTK_InitSynth
doesn't fix the sound, although MPTK_ChannelBankGetIndex
returns 0 after running it.
I'm not familiar with SoundFonts, how do I reload it and perhaps what causes it
to unload? (edited)MidiPlayerGlobal
manages soundfont, which doesn't sound promising for this case. Surely there is a
way to have each midi play with a different sf, right??
For now I found a WAR: merge soundfonts and override channels on different MIDIs.
Ideally, the solution is to allow multiple soundfonts to be loaded. (edited) midiFilePlayer.MPTK_ChannelVolumeSet(15, 0.00001f);
string filename = Path.Combine(Application.persistentDataPath, midiFilePlayer.MPTK_MidiName + "2.mid");
MidiFileWriter2 mfw = new MidiFileWriter2(midiFilePlayer.MPTK_DeltaTicksPerQuarterNote, 1);
mfw.MPTK_LoadFromMPTK(midiFilePlayer.MPTK_MidiEvents, midiFilePlayer.MPTK_TrackCount);
mfw.MPTK_WriteToFile(filename);
Debug.Log("saved file " + filename);
Channel 15 still has its normal volume. Is there any way to change this? (edited)
midiFilePlayer.MPTK_ChannelVolumeSet(15, 0.00001f);
string filename = Path.Combine(Application.persistentDataPath, midiFilePlayer.MPTK_MidiName + "2.mid");
MidiFileWriter2 mfw = new MidiFileWriter2(midiFilePlayer.MPTK_DeltaTicksPerQuarterNote, 1);
mfw.MPTK_LoadFromMPTK(midiFilePlayer.MPTK_MidiEvents, midiFilePlayer.MPTK_TrackCount);
mfw.MPTK_WriteToFile(filename);
Debug.Log("saved file " + filename);
Channel 15 still has its normal volume. Is there any way to change this?
(edited) private static void example(MidiStreamPlayer player)
{
List<MPTKEvent> notes = new List<MPTKEvent>();
for (int i = 0; i < 5; i++)
{
notes.Add(new MPTKEvent()
{
Command = MPTKCommand.NoteOn,
Value = 60,
Channel = 0,
Duration = 1000,
Velocity = 100,
Delay = i * 1000,
});
}
player.MPTK_PlayEvent(notes);
}
private static void example(MidiStreamPlayer player)
{
List<MPTKEvent> notes = new List<MPTKEvent>();
for (int i = 0; i < 5; i++)
{
notes.Add(new MPTKEvent()
{
Command = MPTKCommand.NoteOn,
Value = 60,
Channel = 0,
Duration = 1000,
Velocity = 100,
Delay = i * 1000,
});
}
player.MPTK_PlayEvent(notes);
}
private static void example(MidiStreamPlayer player)
{
List<MPTKEvent> notes = new List<MPTKEvent>();
for (int i = 0; i < 5; i++)
{
notes.Add(new MPTKEvent()
{
Command = MPTKCommand.NoteOn,
Value = 60,
Channel = 0,
Duration = 1000,
Velocity = 100,
Delay = i * 1000,
});
}
player.MPTK_PlayEvent(notes);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// Assign our "Hello, World!"-equivalent note (using MPTKEvent's defaults plus Value = 60 for C5.
// HelperNoteLabel class could be your friend)
mptkEvent = new MPTKEvent() { Value = 60 };
// Start playing our "Hello, World!"-equivalent note
midiStreamPlayer.MPTK_PlayEvent(mptkEvent);
}
else if (Input.GetKeyUp(KeyCode.Space))
{
// Stop playing our "Hello, World!"-equivalent note
midiStreamPlayer.MPTK_StopEvent(mptkEvent);
}
}
(edited)void Start()
{
// Find existing MidiFilePlayer in the scene hierarchy
// ---------------------------------------------------
midiFilePlayer = FindObjectOfType<MidiFilePlayer>();
// ...
// triggered when MIDI starts playing (Indeed, will be triggered at every beginning of loop)
midiFilePlayer.OnEventStartPlayMidi.AddListener(StartPlay);
// ...
}
/// <summary>@brief
/// Start playing MIDI: MIDI File is loaded and Midi Synth is initialized, but so far any MIDI event has been read.
/// This is the right time to defined some specific behaviors.
/// </summary>
/// <param name="midiname"></param>
public void StartPlay(string midiname)
{
// Enable or disable MIDI channel
for (int channel = 0; channel < 16; channel++)
midiFilePlayer.MPTK_ChannelEnableSet(channel, channel == ChannelSelected || ChannelSelected == -1 ? true : false);
// ...
}
(edited)mfw.MPTK_MidiEvents.Insert(0, noteEvent);
mfw.MPTK_StableSortEvents();
but i've noticed that even with the
midiPlayer.MPTK_ModeStopVoice = MidiFilePlayer.ModeStopPlay.StopNoWaiting;
, if i insert a new note towards the end of the sequence, it feels like the new note
waits so it extends the time in between notes.fluid_synth_alloc_voice - Clip Grand-Piano-Dd5 not ready to play Loading
UnityEngine.DebugLogHandler:Internal_Log(LogType, LogOption, String, Object)
UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
UnityEngine.Logger:LogFormat(LogType, String, Object[])
UnityEngine.Debug:LogWarningFormat(String, Object[])
MidiPlayerTK.MidiSynth:fluid_synth_alloc_voice(HiSample, Int32, Int32, Int32, Int32)
MidiPlayerTK.MidiSynth:synth_noteon(MPTKEvent)
MidiPlayerTK.MidiSynth:MPTK_PlayDirectEvent(MPTKEvent, Boolean)
MidiPlayerTK.<ThreadLegacyPlay>d__137:MoveNext()
<CancelWith>d__4:MoveNext()
MEC.Routine:Update()
Added the screenshot from MidiSynth.cs that throws this error.
fluid_synth_alloc_voice - Clip Grand-Piano-Dd5 not ready to play Loading
UnityEngine.DebugLogHandler:Internal_Log(LogType, LogOption, String, Object)
UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
UnityEngine.Logger:LogFormat(LogType, String, Object[])
UnityEngine.Debug:LogWarningFormat(String, Object[])
MidiPlayerTK.MidiSynth:fluid_synth_alloc_voice(HiSample, Int32, Int32, Int32, Int32)
MidiPlayerTK.MidiSynth:synth_noteon(MPTKEvent)
MidiPlayerTK.MidiSynth:MPTK_PlayDirectEvent(MPTKEvent, Boolean)
MidiPlayerTK.<ThreadLegacyPlay>d__137:MoveNext()
<CancelWith>d__4:MoveNext()
MEC.Routine:Update()
Added the screenshot from MidiSynth.cs that throws this error.
midiPlayer.OnEventNotesMidi.AddListener((List<MPTKEvent> events) => {
foreach (MPTKEvent mptkEvent in events)
if (mptkEvent.Command == MPTKCommand.NoteOn)
foreach (INotePlayedListener listener in notePlayedListeners) {
listener.OnNotePlayed();
Debug.Log("Note played at tick " + mptkEvent.Tick);
}
});
where the last note's event doesn't get logged sometimes. It seems to happen
sporadically when using Stop When All Voices Released. Stop No Waiting it happens more,
and Stop When All Voices Ended seems to never skip the last event midiPlayer.OnEventNotesMidi.AddListener((List<MPTKEvent> events) => {
foreach (MPTKEvent mptkEvent in events)
if (mptkEvent.Command == MPTKCommand.NoteOn)
foreach (INotePlayedListener listener in notePlayedListeners) {
listener.OnNotePlayed();
Debug.Log("Note played at tick " + mptkEvent.Tick);
}
});
where the last note's event doesn't get logged sometimes. It seems to happen
sporadically when using Stop When All Voices Released. Stop No Waiting it happens
more, and Stop When All Voices Ended seems to never skip the last event
SustainOn = new MPTKEvent { Command = MPTKCommand.ControlChange, Controller = MPTKController.Sustain, Channel = channel, Value = 0 };
SustainOn = new MPTKEvent { Command = MPTKCommand.ControlChange, Controller = MPTKController.Sustain, Channel = channel, Value = 127 };
value of the command yet it still sustains.
(edited)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MidiPlayerTK;
public class SustainTest : MonoBehaviour
{
[SerializeField]
public MidiStreamPlayer midiStreamPlayer;
public void SustainOn()
{
midiStreamPlayer.MPTK_PlayEvent(new MPTKEvent() { Command = MPTKCommand.ControlChange, Controller = MPTKController.Sustain,Channel = 0, Value = 127 });
}
public void SustainOff()
{
midiStreamPlayer.MPTK_PlayEvent(new MPTKEvent() { Command = MPTKCommand.ControlChange, Controller = MPTKController.Sustain, Channel = 0, Value = 0 });
}
public void NoteOn()
{
midiStreamPlayer.MPTK_PlayEvent(new MPTKEvent() { Command = MPTKCommand.NoteOn, Channel = 0, Value = 60, Velocity = 100 });
}
public void NoteOff()
{
midiStreamPlayer.MPTK_PlayEvent(new MPTKEvent() { Command = MPTKCommand.NoteOff, Channel = 0, Value = 60, });
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
In this example, I press a button for note on, as the note plays I press the sustain on button. I then press
the sustain off button yet nothing happens. Thanks in advance! private MidiFileWriter2 CreateMidiStream_one_note_ticks()
{
// In this demo, we are using variable to contains tracks and channel values only for better understanding.
// Using multiple tracks is not mandatory, you can arrange your song as you want.
// But first track (index=0) is often use for general MIDI information track, lyrics, tempo change. By convention contains no noteon.
int track0 = 0;
// Second track (index=1) will contains the notes, preset change, .... all events associated to a channel.
int track1 = 1;
int channel0 = 0; // we are using only one channel in this demo
long absoluteTime = 0;
// Create a Midi file of type 1 (recommended)
MidiFileWriter2 mfw = new MidiFileWriter2();
mfw.MPTK_AddTimeSignature(0, 0, 4, 4);
// 240 is the default. A classical value for a Midi. define the time precision.
int ticksPerQuarterNote = mfw.MPTK_DeltaTicksPerQuarterNote;
// Some textual information added to the track 0 at time=0
mfw.MPTK_AddText(
track0,
0,
MPTKMeta.Copyright,
"Simple MIDI Generated. 4 quarter at 120 BPM"
);
// Define Tempo is not mandatory when using time in ticks. The default 120 BPM will be used.
//mfw.MPTK_AddBPMChange(track0, 0, 120);
mfw.MPTK_AddNote(
track1,
absoluteTime,
channel0,
UnityEngine.Random.Range(41, 80),
50,
ticksPerQuarterNote
);
// mfw.MPTK_AddSilence(track1, absoluteTime, channel0, ticksPerQuarterNote * 2);
return mfw;
}
private MidiFileWriter2 CreateMidiStream_one_note_ticks()
{
// In this demo, we are using variable to contains tracks and channel values only for better understanding.
// Using multiple tracks is not mandatory, you can arrange your song as you want.
// But first track (index=0) is often use for general MIDI information track, lyrics, tempo change. By convention contains no noteon.
int track0 = 0;
// Second track (index=1) will contains the notes, preset change, .... all events associated to a channel.
int track1 = 1;
int channel0 = 0; // we are using only one channel in this demo
long absoluteTime = 0;
// Create a Midi file of type 1 (recommended)
MidiFileWriter2 mfw = new MidiFileWriter2();
mfw.MPTK_AddTimeSignature(0, 0, 4, 4);
// 240 is the default. A classical value for a Midi. define the time precision.
int ticksPerQuarterNote = mfw.MPTK_DeltaTicksPerQuarterNote;
// Some textual information added to the track 0 at time=0
mfw.MPTK_AddText(
track0,
0,
MPTKMeta.Copyright,
"Simple MIDI Generated. 4 quarter at 120 BPM"
);
// Define Tempo is not mandatory when using time in ticks. The default 120 BPM will be used.
//mfw.MPTK_AddBPMChange(track0, 0, 120);
mfw.MPTK_AddNote(
track1,
absoluteTime,
channel0,
UnityEngine.Random.Range(41, 80),
50,
ticksPerQuarterNote
);
// mfw.MPTK_AddSilence(track1, absoluteTime, channel0, ticksPerQuarterNote * 2);
return mfw;
}
public class MidiNotePlayer : MonoBehaviour {
public MidiStreamPlayer midiStreamPlayer;
public string midiName = "Animal Crossing";
private List<MPTKEvent> midiEvents;
private int currentNoteIndex = 0;
void Start() {
LoadMidiEvents();
}
void LoadMidiEvents() {
var midiLoad = new MidiLoad();
midiLoad.MPTK_Load(midiName);
midiEvents = midiLoad.MPTK_ReadMidiEvents();
}
public void PlayNextNote() {
if (midiStreamPlayer == null) {
Debug.LogError("MidiStreamPlayer is not assigned!");
return;
}
if (midiEvents == null || midiEvents.Count == 0) {
Debug.Log("No MIDI events loaded.");
return;
}
bool notePlayed = false;
// Start a loop to handle simultaneous notes
while (currentNoteIndex < midiEvents.Count) {
MPTKEvent midiEvent = midiEvents[currentNoteIndex];
if (midiEvent.Command == MPTKCommand.NoteOn && midiEvent.Velocity > 0) {
midiStreamPlayer.MPTK_PlayEvent(midiEvent);
notePlayed = true;
}
currentNoteIndex++;
if (currentNoteIndex >= midiEvents.Count) {
currentNoteIndex = 0;
if (notePlayed) break;
} else if(notePlayed && (currentNoteIndex >= midiEvents.Count || midiEvents[currentNoteIndex].RealTime != midiEvent.RealTime)) {
break;
}
}
}
}
(edited)if (midiEvent.Command == MPTKCommand.NoteOn && midiEvent.Velocity > 0) {
midiStreamPlayer.MPTK_PlayEvent(midiEvent);
notePlayed = true;
}
(edited)
midiStreamPlayer.MPTK_PlayEvent(midiEvent);
notePlayed = true;
(edited)
private void Start()
{
....
midiExternalPlayer.OnEventStartPlayMidi.AddListener(StartPlay);
....
}
public void StartPlay(string midiname)
{
Debug.Log("Start Midi " + midiname + " Duration: " + midiExternalPlayer.MPTK_Duration.TotalSeconds + " seconds");
midiExternalPlayer.MPTK_InnerLoop.Enabled = true;
midiExternalPlayer.MPTK_InnerLoop.Start = 10000;
midiExternalPlayer.MPTK_InnerLoop.Resume = 10000;
midiExternalPlayer.MPTK_InnerLoop.End = 10200;
midiExternalPlayer.MPTK_InnerLoop.Log = true;
// midiExternalPlayer.MPTK_Speed = 1f;
// midiExternalPlayer.MPTK_Transpose = 0;
}
(edited)// Display current measure and beat value of the last MIDI event read by the MIDI sequencer.
Debug.Log($"MPTK_NumberBeatsMeasure: {midiExternalPlayer.midiLoaded.MPTK_NumberBeatsMeasure} MPTK_CurrentMeasure: {midiExternalPlayer.MPTK_MidiLoaded.MPTK_CurrentMeasure}.{midiExternalPlayer.MPTK_MidiLoaded.MPTK_CurrentBeat} - Last measure: {midiExternalPlayer.MPTK_MidiLoaded.MPTK_MeasureLastNote}");
// Display current measure and beat value
if (midiExternalPlayer.midiLoaded != null)
{
Debug.Log($"MPTK_NumberBeatsMeasure: {midiExternalPlayer.midiLoaded.MPTK_NumberBeatsMeasure} MPTK_CurrentMeasure: {midiExternalPlayer.MPTK_MidiLoaded.MPTK_CurrentMeasure}.{midiExternalPlayer.MPTK_MidiLoaded.MPTK_CurrentBeat}");
// Calculate tick position of a measure (just for a demo how to calculate tick from bar).
// So, it's easy to create loop based on measure.
Debug.Log($"Tick for the current measure: {MPTKSignature.MeasureToTick(midiExternalPlayer.MPTK_MidiLoaded.MPTK_SignMap, midiExternalPlayer.MPTK_MidiLoaded.MPTK_CurrentMeasure)}");
}
/// <summary>@brief
/// Play 3x4 quarters with a tempo change.
/// </summary>
/// <returns></returns>
private MPTKWriter CreateMidiStream_tempochange()
{
MPTKWriter mfw = new MPTKWriter(deltaTicksPerQuarterNote: 500);
mfw.AddBPMChange(1, 0 * mfw.DeltaTicksPerQuarterNote, 60);
mfw.AddNote(1, 0 * mfw.DeltaTicksPerQuarterNote, 0, 60, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddNote(1, 1 * mfw.DeltaTicksPerQuarterNote, 0, 61, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddNote(1, 2 * mfw.DeltaTicksPerQuarterNote, 0, 62, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddNote(1, 3 * mfw.DeltaTicksPerQuarterNote, 0, 63, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddBPMChange(1, 4 * mfw.DeltaTicksPerQuarterNote, 120);
mfw.AddNote(1, 4 * mfw.DeltaTicksPerQuarterNote, 0, 60, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddNote(1, 5 * mfw.DeltaTicksPerQuarterNote, 0, 61, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddNote(1, 6 * mfw.DeltaTicksPerQuarterNote, 0, 62, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddNote(1, 7 * mfw.DeltaTicksPerQuarterNote, 0, 63, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddBPMChange(1, 8 * mfw.DeltaTicksPerQuarterNote, 240);
mfw.AddNote(1, 8 * mfw.DeltaTicksPerQuarterNote, 0, 60, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddNote(1, 9 * mfw.DeltaTicksPerQuarterNote, 0, 61, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddNote(1, 10 * mfw.DeltaTicksPerQuarterNote, 0, 62, 60, mfw.DeltaTicksPerQuarterNote);
mfw.AddNote(1, 11 * mfw.DeltaTicksPerQuarterNote, 0, 63, 60, mfw.DeltaTicksPerQuarterNote);
return mfw;
}
private void PatchChange(int patch)
{
LastTimeActivity = Time.realtimeSinceStartup;
SeqTimeUpdate = true;
// Play the change directly
midiStreamPlayer.MPTK_PlayEvent(new MPTKEvent { Command = MPTKCommand.PatchChange, Value = patch, Channel = StreamChannel });
// Add midi event "Preset Change" to the midifilewriter object
long tickFromTime = midiFileWriter.ConvertMilliToTick(CurrentTimeMs);
//midiFileWriter.AddChannelAfterTouch(trackNo, tickFromTime, StreamChannel, patch);
midiFileWriter.AddChangePreset(trackNo, tickFromTime, StreamChannel, patch);
}
if (presetNameText)
presetNameText.text = midiStreamPlayer.MPTK_Channels[StreamChannel].PresetName;
midiStreamPlayer.MPTK_Channels[StreamChannel].PresetName
,
i have to wait a frame after the PatchChange
function is called (In the beginning of the Script only). //Wait till the MPTK_Channels has initialised,
//and apply the default patch number added in from the inspector
if(midiStreamPlayer.MPTK_Channels.Length>0)
{
if (!defaultPatchSet)
{
StartCoroutine(ChangePatch(defaultPatchNumber));
defaultPatchSet = true;
Debug.Log("Default patch has been set");
}
}
private void PatchChange(int patch)
{
LastTimeActivity = Time.realtimeSinceStartup;
SeqTimeUpdate = true;
// Play the change directly
midiStreamPlayer.MPTK_PlayEvent(new MPTKEvent { Command = MPTKCommand.PatchChange, Value = patch, Channel = StreamChannel });
// Add midi event "Preset Change" to the midifilewriter object
long tickFromTime = midiFileWriter.ConvertMilliToTick(CurrentTimeMs);
//midiFileWriter.AddChannelAfterTouch(trackNo, tickFromTime, StreamChannel, patch);
midiFileWriter.AddChangePreset(trackNo, tickFromTime, StreamChannel, patch);
}
case "PATCH_INST":
CurrentPreset = index;
if (Test_MPTK_ChannelPresetChange)
midiStreamPlayer.MPTK_Channels[StreamChannel].PresetNum = index;
else
midiStreamPlayer.MPTK_PlayEvent(new MPTKEvent() { Command = MPTKCommand.PatchChange, Value = index, Channel = StreamChannel, });
Debug.Log($"Instrument Preset change - channel:{StreamChannel} bank:{midiStreamPlayer.MPTK_Channels[StreamChannel].BankNum} preset:{midiStreamPlayer.MPTK_Channels[StreamChannel].PresetNum}");
(edited) if (presetNameText)
presetNameText.text = midiStreamPlayer.MPTK_Channels[StreamChannel].PresetName;
midiStreamPlayer.MPTK_Channels[StreamChannel].PresetName;
a delay could occurs until the MIDI event Command = MPTKCommand.PatchChange
is effectively run by the MIDI synth which is running in another threadMidiPlayerGlobal.MPTK_PresetName(CurrentPreset);