ncassetta / NiCMidi

A MIDI C++ library with objects for reading, writing, playing, editing and recording midi files
GNU Lesser General Public License v3.0
2 stars 1 forks source link

Crash when use AdvancedSequencer::AdvancedSequencer(MIDISequencerGUINotifier *n) #6

Closed ncassetta closed 2 years ago

ncassetta commented 2 years ago

this was reported to me by goofy2k in another issue. The cause should be a missing line in AdvancedSequencer::AdvancedSequencer (MIDISequencerGUINotifier * n) For @goofy2k: try inserting this line after advancedsequencer.cpp::116

From

116:    MIDIManager::AddMIDITick(this);
117:    // sets the embedded MIDIThru only if the system has almost an in port
118:    if (MIDIManager::IsValidInPortNumber(0)) {

to

116:    MIDIManager::AddMIDITick(this);
117:    ExtractWarpPositions();
118:    // sets the embedded MIDIThru only if the system has almost an in port
119:    if (MIDIManager::IsValidInPortNumber(0)) {
ncassetta commented 2 years ago

@goofy2k If you agree I would close the old issue, we can continue here. The correction I propose should avoid the crash (I hope! :-) ), but, as I said, recording on a loop should bring unpredictable results as this feature wasn't finished yet.

Let me know if your program continues to crash and if your line

if (recorder.SetTrackRecChannel(1,0)) { //

gives true

goofy2k commented 2 years ago

@ncassetta,

1) Note that my advancedsequencer code was not in the "clean" state. I had lines 118-123 commented for some reason during my development. I uncommented it now again . The crash then still takes place.

2) After I added ExtractWarpPositions() as suggested by you, the immdiate crash (after recorder.Start() dissappears! I get a (varying) number of GUI EVENT reports, followed by a timer error:

GUI EVENT: Transport MEAS 6 BEAT 0 GUI EVENT: Transport MEAS 6 BEAT 1 GUI EVENT: Transport MEAS 6 BEAT 2 GUI EVENT: Transport MEAS 6 BEAT 3 GUI EVENT: Transport MEAS 7 GUI EVENT: Transport MEAS 7 BEAT 0 GUI EVENT: Transport MEAS 7 BEAT 1 GUI EVENT: Transport MEAS 7 BEAT 2 E (18640) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time: E (18640) task_wdt: - IDLE1 (CPU 1) E (18640) task_wdt: Tasks currently running: E (18640) task_wdt: CPU 0: btController E (18640) task_wdt: CPU 1: pthread E (18640) task_wdt: Print CPU 0 (current core) backtrace

I will investigate this. Suggestions welcome of course !

Should I keep the ExtractWarpPositions in place?

3) My if (recorder.SetTrackRecChannel(1,0)) line gives TRUE as I don't see my added error logs that would appear if the result were FALSE.

4) With respect to closing of the old issue: I will respond in Issue #5. If that is the one that you mean with "old issue".

ncassetta commented 2 years ago

@goofy2k Try this:

MIDISequencerGUINotifierText text_n;        // the AdvancedSequencer GUI notifier
AdvancedSequencer sequencer(&text_n);       // an AdvancedSequencer (with GUI notifier)
MIDIRecorder recorder(&sequencer);          // a MIDIRecorder //FCKX

int main( int argc, char **argv ) {

    MIDIManager::AddMIDITick(&recorder);
    //text_n.SetSequencer(&sequencer);      // This is already called by AdvancedSequencer constructor

    MIDIClockTime t = sequencer.MeasToMIDI(5,0); //endMeasure, endBeat record the first 6 beats
    recorder.SetEndRecTime(t);
    recorder.EnableTrack(1); //FCKX
    recorder.SetTrackRecChannel(1,-1);      // Can you set this? Otherwise set a specific channel

    recorder.Start();
    std::cout << "Recorder started\n";

    MIDITimer::Wait(15000);                 // Waits 15 secs: play something to record (remember to match
                                            // the input channel with the one set in SetTrackRecChannel)

    recorder.Stop();
    std::cout << "Recorder stopped\n";

    sequencer.GoToZero();                   // rewinds
    sequencer.Start();
    std::cout << "Now the sequencer plays what you have recorded\n";

    while (sequencer.IsPlaying())         // waits until the sequencer finishes
        MIDITimer::Wait(50);
}

(replace cout with your log)

This should allow you to record: you should hear the metronome, with the count-in measure (or at least see the notifier which prints the beats) and then you can record. Finally the sequencer is rewinded and should play your recording. Does it work?

Yes, I was unclear, for "old issue" I intended #2 , which is solved

goofy2k commented 2 years ago

This throws an error. The backtrace starts at the newly added:

ExtractWarpPositions() (advancedsequencer.cpp:~118)
while (MIDISequencer::GoToMeasure (num_warp_positions MEASURES_PER_WARP)) (advancedsequencer.cpp:~733) MIDISequencerState old_state = state; (sequencer.cpp:~797) track_states[i] = new MIDISequencerTrackState(s.track_states[i]) (sequencer.cpp:~86) ... ... xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:47 without reporting the specific reason

[EDIT] I hear the metronome, see the BEAT reports from the notifier, DON'T hear the played notes on input (as before)

goofy2k commented 2 years ago

When I remove the ExtractWarpPositions() (advancedsequencer.cpp:~118)

I can record (without hearing the notes this time) and the error occurs after the Stop() command:

ExtractWarpPositions() (advancedsequencer.cpp:~702) <<< a different location than before while (MIDISequencer::GoToMeasure (num_warp_positions * MEASURES_PER_WARP)) (advancedsequencer.cpp:~733) ...etc ...etc

goofy2k commented 2 years ago

I tried to drastically increase stack sizes, without success.

goofy2k commented 2 years ago

This is the last output:

GATT procedure initiated: notify; att_handle=12 GATT procedure initiated: notify; att_handle=12 OUT Port fckx_seq closed GUI EVENT: Transport SEQUENCER STOP ... Exiting from MIDISequencer::Stop()

abort() was called at PC 0x4014ba47 on core 0 0x4014ba47: cxxabiv1::terminate(void (*)()) at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:47

GATT has to do with my nimBLE output I don't have very useful hits when I search Google for the last line....

goofy2k commented 2 years ago

The error occurs at track_states[i] = new MIDISequencerTrackState(*s.track_states[i]) (sequencer.cpp:~86) for i == 15 !

It appears that track_states.size() equals 17. I tried to decrease the range of the loop. Then I see that the loop is executed multiple times. In the third time a different error occurs. This time at:

/include/sequencer.h:53
sequencer.cpp:122 track_states[i] = new MIDISequencerTrackState(*s.track_states[i]);

It looks like something is wrong with the value of track_states.size() ???

ncassetta commented 2 years ago

1) The ExtractWarpPosition at advancedsequencer.cpp:118 must remain 2) So you can arrive until stopping the recorder: what is the last Transport event (meas/beat?). It's difficult for me because I don't have any error here. I'll try to investigate today.

goofy2k commented 2 years ago

I see the stop log and then several beats tick before the crash. I'll send you the log output....

Op di 21 dec. 2021 06:33 schreef Nicola Cassetta @.***>:

  1. The ExtractWarpPosition at advancedsequencer.cpp:118 must remain
  2. So you can arrive until stopping the recorder: what is the last Transport event (meas/beat?). It's difficult for me because I don't have any error here. I'll try to investigate today.

— Reply to this email directly, view it on GitHub https://github.com/ncassetta/NiCMidi/issues/6#issuecomment-998486959, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGII3TWQX4U2VV5N73KOFSDUSAGUFANCNFSM5KL2VZ2A . You are receiving this because you were mentioned.Message ID: @.***>

goofy2k commented 2 years ago

Here is my log output. I saved the state of the v23 code to the repo. As it is not completely clean... Runtime error v23 .txt .

ncassetta commented 2 years ago

@goofy2k I committed some changes, only in files sequencer.h, sequencer.cpp, advancedsequencer.cpp, recorder.cpp. These address another bug I found, apparently unrelated to this. But this crash in the constructor of MIDISequencerState is very strange: the two vectors should always have the same size, I added also a log (which never is triggered), so it could be due to odd causes. Let me know if something changes.

goofy2k commented 2 years ago

OK, I will have a look. For my convenience: can you please give the names of the two vectors that should always be the same.

goofy2k commented 2 years ago

Don't mind ! I see the two vectors in your added log lines!

goofy2k commented 2 years ago

I now see a slightly different behavior: NO beats visible in the console at all.

I only see my log lines, right after Exiting MIDIManager::Init():

E (696) NICMIDI DRIVER: start creation of MQTTMidiIn port W (702) MQTTDRIVER: MQTTMidiIn instantiation W (707) MQTTDRIVER: MQTTMidiIn :: initialize E (712) MQTTDRIVER: MQTTMidiIn::setCallback: STORING CALLBACK IN inputData_ E (719) NICMIDI DRIVER: executed creation of MQTTMidiIn port Exiting MIDIManager::Init() Found 1 midi out and 1 midi in E (731) SEQUENCER: track_states.size() 17 E (735) SEQUENCER: BEFORE new MIDISequencerTrackState(s.track_states[i]) for i 0 E (743) SEQUENCER: AFTER new MIDISequencerTrackState(s.track_states[i]) for i 0 etc. etc. Then a crash after 2 sets of 17 calls of new MIDISequencerTrackState(*s.track_states[i]) for i 0 + 1 last set where the crash occurs in this line for i equal 7

goofy2k commented 2 years ago

1) I don't see your new logs at all 2) I am not sure that I correctly took over you change at recorder.cpp 455-456 491 in my V24 version

[EDIT] I checked these lines. I believe your and my codes are equivalent. I only added a logging trick by using the fact that (tracks->InsertEvent(i, msg)) returns a boolean.

I will make the codes exactly equal to make sure that they are indeed the same. [DONE, no changes]

goofy2k commented 2 years ago

I will investigate if this error has something to do with the status of MIDIMatrix.

ncassetta commented 2 years ago

Perhaps the bug is due to the lack of the copy constructor of the MIDISequencerTrackState class. I didn't declare it in sequencer.h (see sequencer.h:53 onward), leaving the compiler to implement it. Another problem could be the signedness of char: I supposed the default char to be signed, but this should depend from the compiler I tried these changes in files sequencer.h and sequencer.cpp. This should let to a lot of logs as the constructor is called once for every track. At least, this should allow you to trace the execution inside the construction of the MIDISequencerTrackState objects.

Test.txt .

goofy2k commented 2 years ago

Thanks. I will give this a try ! I am investigating memory usage. Also try to run the app on a different board. Then I see slightly different behaviour.

I now encounter a watchdog error on timer.ccp:124. I am not familiar with thread and sleep. More with freertos tasks an delay.....

I will try some things further before discussing details. Otherwise this becomes to confusing :-).

Op wo 22 dec. 2021 12:41 schreef Nicola Cassetta @.***>:

Perhaps the bug is due to the lack of the copy constructor of the MIDISequencerTrackState class. I didn't declare it in sequencer.h (see sequencer.h:53 onward), leaving the compiler to implement it. Another problem could be the signedness of char: I supposed the default char to be signed, but this should depend from the compiler I tried these changes in files sequencer.h and sequencer.cpp. This should let to a lot of logs as the constructor is called once for every track. At least, this should allow you to trace the execution inside the construction of the MIDISequencerTrackState objects.

Test.txt https://github.com/ncassetta/NiCMidi/files/7762344/Test.txt .

— Reply to this email directly, view it on GitHub https://github.com/ncassetta/NiCMidi/issues/6#issuecomment-999512565, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGII3TTQSX3WE5NLGHIJF7LUSG2QNANCNFSM5KL2VZ2A . You are receiving this because you were mentioned.Message ID: @.***>

goofy2k commented 2 years ago

It looks that I have something! The timer error on the new (a TTGO TAudio) board for running the NiCMidi sequencer was caused because it was waiting for a nimBLE detection with the other TTGO TAudio running the synth.

When I boot them in the right order the sequencer finishes the recording loop without crashing.

NOTE: the nimBLE connection error is NOT the cause of this all. I all the experiments with the original board (Heltec LORA32) I properly established the nimBLE connection.

I now have this log. Did notremove any info. After stopping of the recorder the new MIDISequencerTrackState(*s.track_states[i]) loops are properly executed till the end.

Until GUI EVENT: All GENERAL RESET Now the sequencer plays what you have recorded [EDIT]: this is a message. Untill now I didn't see notes going to the output

goofy2k commented 2 years ago

Here is the log: runtime log TTGO TAudio V24.txt

When I play some notes, the code hangs after stopping......

More later!

ncassetta commented 2 years ago

If you still have the warning of the #5 I suspect a mismatch between signed and unsigned char in MIDIRecorder::TickProc. Try to insert a log after recorder.cpp:453

    if (ch1 == ch2 || ch2 == -1) {         // try to change -1 with 255
            // insert the event into the track
            tracks->InsertEvent(i, msg);
            std::cout << "Message recorder on track " << i << std::endl;
       }

you should see it at every note you record

goofy2k commented 2 years ago

You're right. Take care of warnings before they can become bugs!

I see this message on every note only ifff I change the -1 to 255.

If I don't change the -1 I do see a "Got message, queue size: 1" . But that is probably a trace earlier in the chain....

SO: I will change to 225 here.

goofy2k commented 2 years ago

There is another warning in my compiler output:

if (IsPlaying() || !tracks->IsValidTrackNumber(trk_num) || (chan < -1 || chan > 15))

I believe this one is a bit more tricky to repair. In "pseudo code":

chan < -1 must be replaced by 127 < chan < 255 ??
chan > 15 must be replaced by 15 < chan < 128 ??

Maybe implement this by masking bit 7 ?

goofy2k commented 2 years ago

When NOT recording any note, the code stops recording. It gives:

GUI EVENT: All GENERAL RESET ... Exiting from MIDIRecorder::Stop() Recorder stopped GUI EVENT: All GENERAL RESET E (24878) SEQUENCER: track_states.size() 17 E (24878) SEQUENCER: BEFORE new MIDISequencerTrackState(s.track_states[i]) for i 0 E (24888) SEQUENCER: AFTER new MIDISequencerTrackState(s.track_states[i]) for i 0 E (24898) SEQUENCER: BEFORE new MIDISequencerTrackState(s.track_states[i]) for i 1 E (24908) SEQUENCER: AFTER new MIDISequencerTrackState(s.track_states[i]) for i 1 E (24908) SEQUENCER: BEFORE new MIDISequencerTrackState(s.track_states[i]) for i 2 E (24918) SEQUENCER: AFTER new MIDISequencerTrackState(s.track_states[i]) for i 2 etc. etc. and then hangs without any sign of life after:

E (25108) SEQUENCER: BEFORE new MIDISequencerTrackState(s.track_states[i]) for i 14 E (25118) SEQUENCER: AFTER new MIDISequencerTrackState(s.track_states[i]) for i 14 E (25138) SEQUENCER: BEFORE new MIDISequencerTrackState(s.track_states[i]) for i 15 E (25138) SEQUENCER: AFTER new MIDISequencerTrackState(s.track_states[i]) for i 15 E (25148) SEQUENCER: BEFORE new MIDISequencerTrackState(s.track_states[i]) for i 16 E (25158) SEQUENCER: AFTER new MIDISequencerTrackState(s.track_states[i]) for i 1

The "GUI EVENT: All GENERAL RESET" appears 5 times in this process!

ncassetta commented 2 years ago

Perhaps I have resolved the crash when the sequencer stops. This has required a new commit, with changes in advancedsequencer.cpp sequencer.h and sequencer.cpp. It seems that the explicit copy constructor of MIDISequencerTrackState isn't needed, so I commented it I must revise all comparison between MIDI channel taking into account that the char are unsigned. However the line you signal is only relevant for excluding wrong channel numbers, so if you give correct channel numbers it doesn't matter.

ncassetta commented 2 years ago

I prepared a modified version of test_writefile without user input and file loading, can you try it? IT only involves AdvancedSequencer, and you should hear "twinkle twinkle". Just rename .txt into .cpp test_advancedsequencer_noinput.txt

goofy2k commented 2 years ago

Yes I can hear the notes! I get a lot more logs on the console.

goofy2k commented 2 years ago

Somehow the code is looping and then causes a crash. This may be due to the fact that I hade to embed it in my app to make the nimBLE output available. I did not yet have a good look at your code.

goofy2k commented 2 years ago

Learning a lot from this.

Trying to detect the reason for the looping. I let the program cycle for 3 repeats of the song. Without success yet. I changed the " Stop" into " NiCMidiStop" to better find it in my logs. But it isn't there. So there seems to be some error in running the end of this code.

I will add 2 files here:

logtofile.txt is the monitor output logged to file morelog.txt is the esp-idf related log that still appeared in the terminal screen

logtofile.txt morelog.txt

Other observations:

The looping doesn't look like reboots.

It looks that I am only hearing one track. But that could be because my synths Midi input only detects channel 0.

My nimBLE interface is re-initialised every time that the the Manager is started. I'll have to introduce a better test if the port is already open.

goofy2k commented 2 years ago

Other question: I am thinking ahead.... To take control in a UI/GUI I want to redirect the dump_track info etc. .For example to MQTT or nimBLE. You have built in an option to replace std:cout by another stream (ostream* ost in the dump_tracks.cpp functions). So, I am trying to build a class that intercepts that output and casts it into a stream for MQTT or nimBLE. Do you have such an interceptor in place for some output. If so, that could help. I not, I will proceed my endeavour.

ncassetta commented 2 years ago

1) First time only one track (a vibraphone) is played, second time vibraphone, bass and drums. Your program, however, crashes when second play begins. I also had this problem and it was solved in the last version I committed. There was a bug in the autostop (which calls Stop() in a different thread), so I had to add a mutex to the MIDISequencer. As I said above, in the last commit only some lines of advancedrecorder.cpp, sequencer.h and sequencer.cpp are modified. 2) No, I don't know how MQTT works. However, I think, you can subclass the ostream to get your class

goofy2k commented 2 years ago
  1. What do you mean with "the last version I committed"? Is this the version that you commited today (3 hours ago, +- 20:00)? And does this probably solve the problem that I have with the crash after the first single track?
  2. It doesn't have to deal specifically with MQTT. Any code that intercepts the stream will do. If you don't have it, don't bother ! I ' finf it out.
goofy2k commented 2 years ago

Also: my synth board has only one instrument. For multiple instruments/channels I have two options. Multiple boards or a set of instruments in 1 board. The second option may be too heavy a task for an ESP32 board.

Op wo 22 dec. 2021 23:11 schreef Nicola Cassetta @.***>:

First time only one track (a vibraphone) is played, second time vibraphone, bass and drums. Your program, however, crashes when second play begins. I also had this problem and it was solved in the last version I committed? There was a bug in the autostop (which calls Stop() in a different thread), so I had to add a mutex to the MIDISequencer. As I said above, in the last commit only some lines of advancedrecorder.cpp, sequencer.h and sequencer.cpp are modified.

— Reply to this email directly, view it on GitHub https://github.com/ncassetta/NiCMidi/issues/6#issuecomment-999910776, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGII3TQ66SUCJIWNPGGZK3TUSJEI5ANCNFSM5KL2VZ2A . You are receiving this because you were mentioned.Message ID: @.***>

ncassetta commented 2 years ago

1) Yes, the last version is "bug on autostop corrected". 2) Could your crash be related to the fact that, the second time, the sequencer sends multichannel MIDI? You could make these two checks: 2a) Comment from line 133: to 174: In this way the sequencer only plays once and then the program exits. I hope this shouldn't give no crash (or, if this happens, could be related to the closure of your drivers)

133:    /* THE REST IS COMMENTED OUT. IF YOU SUCCEED CAN UNCOMMENT AND PLAY OTHER TWO TRACKS
                .   .   .
174:    */
175:
176:             return EXIT_SUCCESS;

2b) Comment from line 133: to 165: The sequencer plays, rewinds and plays again without adding other two tracks: this could give a crash if there are still problems with autostop

133:    /* THE REST IS COMMENTED OUT. IF YOU SUCCEED CAN UNCOMMENT AND PLAY OTHER TWO TRACKS
                .   .   .
163:    }
164:
165:    sequencer.UpdateStatus(); */
166:    sequencer.GoToZero();
goofy2k commented 2 years ago

OK, I am currently implementing your last changes. First test it, see how it performs and then turn to these suggestions.

goofy2k commented 2 years ago

After implementing you changes I get some errors that are probably related to that. Most of them contain a reference to AUTO_STOPPED which is now probably obsolete?

I have to see if this is due to inproper implementation of your changes by me.

goofy2k commented 2 years ago

In file included from ../components/NiCMidi/src/../include/advancedsequencer.h:39, from ../main/test_advancedsequencer_noinput.cpp:32: ../components/NiCMidi/src/../include/sequencer.h:499:41: error: 'static void MIDISequencer::StaticStopProc(MIDISequencer)' cannot be overloaded with 'static void MIDISequencer::StaticStopProc(MIDISequencer)' static void StaticStopProc(MIDISequencer p) { p->Stop(); p->state.count_in_status &= ~AUTO_STOPPED;} ^~~~~~ ../components/NiCMidi/src/../include/sequencer.h:494:42: note: previous declaration 'static void MIDISequencer::StaticStopProc(MIDISequencer)' static void StaticStopProc(MIDISequencer p) { p->Stop(); } //NiCMidi 211222 ^~~~~~ ../components/NiCMidi/src/../include/sequencer.h: In static member function 'static void MIDISequencer::StaticStopProc(MIDISequencer)': ../components/NiCMidi/src/../include/sequencer.h:499:119: error: 'AUTO_STOPPED' was not declared in this scope static void StaticStopProc(MIDISequencer p) { p->Stop(); p->state.count_in_status &= ~AUTO_STOPPED;} ^~~~ ../components/NiCMidi/src/../include/sequencer.h:499:119: note: suggested alternative: 'RT_STOP' static void StaticStopProc(MIDISequencer p) { p->Stop(); p->state.count_in_status &= ~AUTO_STOPPED;} ^~~~ RT_STOP

goofy2k commented 2 years ago

one of the messages is because I still have test_advancedsequencer_noinput.cpp in my CMakeLists.txt. I removed that because I pasted the code in my main.cpp

goofy2k commented 2 years ago

For the rest I probably just have to remove the default parameter &= ~AUTO_STOPPED from the function defs

goofy2k commented 2 years ago

I see some misstakes by me.....

goofy2k commented 2 years ago

OK. Still playing 1 single track, then a crash (timer watchdog,...). I will test your suggestions above to get a simpler case and analyse what is going on. Later ! I smell that we are nearby....

goofy2k commented 2 years ago

Your suggestions 2 and 2b run without errors!

In 2 I hear the song, then the program finishes correctly in an endless loop with one repeating log line that I added. In 2b I hear the song. After that it carries out sequencer.GoToZero() (166) and further without crashes and reaches my endless loop. I don't hear any output. For my understanding: should I hear the first track again? By looking at the code, I would say it is just a rewind to the start and play the same again.....

ncassetta commented 2 years ago

Yes, you should hear the music twice. Perhaps this could be related to the fact that your ports doesn't close correctly. Infact the out port opens the first time (by Start()), then is closed by Stop(), and the second time doesn't send messages. You could also add a notifier (as in the example with the recorder) to see what messages are output.

goofy2k commented 2 years ago

OK. Good to know. I can add that notifier. You mean the recorder example from your repo? My receiving synth board also notifies incoming messages, so I can analyze!

When I reduce my log level to get rid of (now obsolete) log output I get a watchdog error again. SO: I am not completely sure that the error is caused by some code that is now commented (the preparation of the next tracks).

I will save a version (v24) that is playing without runtime errors and switch my focus to cleaner handling of the output port. I think it is wise initialize the nimBLE client and create a connection with the synth before any calls to NiCMidi. When preparing the port (Manager/Driver) I must do a check if the connection is OK similar to what is done in RtMidi.

When this is more stable, it will hopefully be clearer where errors occcur.

goofy2k commented 2 years ago

Actually the other tracks ARE received by the synth board! Also some work to do on that side. Now, only channel 0 is handled to generate sound :-)

goofy2k commented 2 years ago

I'll let you know my progress!

ncassetta commented 2 years ago

However I think you should initialize your connection only once (if this is expensive in terms of time) when the ports are created. You should try to have the code of openPort and closePort lighter as possible, as they are called at every sequencer playing,

Moreover, I have some other idea for text_advancedsequencer_noinput:

1) Try to uncomment BEFORE UpdateStatus() at line 165 (it is a somewhat complex method and could cause trouble) 2) Try to add track 2 (bass) on the same channel (so you have same instrument): 2a) Uncomment line 133 2b) Comment ONLY line 137 which changes the channel of the messsages (in this way: // channel = 1) so they remains on channel 0 (aka MIDI 1) 2c) Put a / comment in line 150 ( / ... and 3 (percussion, channel 10) so you don't add the drums which would give trouble 2d) Leave line 165 uncommented, because you must update the sequencer before moving time or playing. 2e) you should hear bass and melody played by the same instrument 2f) If this goes OK you could try to uncomment newly line 137 which sets the second track on channel 2, to see what your synth does.

goofy2k commented 2 years ago

Re ouput port: yes, I want to make opening and closing the port in NiCMidi as light as possible. Most of the work should have been done before calling MIDIManager.

I will test your suggestions as first thing to do in V25 !

I don't understand your nr 1 completely. It could cause trouble. What does it do? We probably need it in the end? I also want to test if I can go back to my original Heltec LORA32 hardware for the sequencer. I now use a TTGO TAudio, which is more expensive. I have 3 of those and want to use them as synths e.g. for other instruments. They have an audio codec onboard, whereas the Heltec board does not.

goofy2k commented 2 years ago

sequencer.UpdateStatus() causes problems....