| 611 | } |
| 612 | |
| 613 | void NoteCanvas::SaveMidi() |
| 614 | { |
| 615 | using namespace juce; |
| 616 | constexpr static int ticksPerQuarterNote = 960; |
| 617 | |
| 618 | FileChooser chooser("Save midi", File(ofToDataPath("midi")), "*.mid", true, false, TheSynth->GetFileChooserParent()); |
| 619 | if (chooser.browseForFileToSave(true)) |
| 620 | { |
| 621 | MidiFile midifile; |
| 622 | midifile.setTicksPerQuarterNote(ticksPerQuarterNote); |
| 623 | MidiMessageSequence track1; |
| 624 | MidiMessage trackTimeSig = MidiMessage::timeSignatureMetaEvent(TheTransport->GetTimeSigTop(), TheTransport->GetTimeSigBottom()); |
| 625 | track1.addEvent(trackTimeSig); |
| 626 | for (auto* element : mCanvas->GetElements()) |
| 627 | { |
| 628 | NoteCanvasElement* noteOnElement = static_cast<NoteCanvasElement*>(element); |
| 629 | int noteNumber = mCanvas->GetNumRows() - noteOnElement->mRow - 1; |
| 630 | float noteStart = (element->mCol + element->mOffset) * ticksPerQuarterNote * |
| 631 | +TheTransport->GetMeasureFraction(mInterval) / TheTransport->GetMeasureFraction(kInterval_4n); |
| 632 | float velocity = noteOnElement->GetVelocity(); |
| 633 | MidiMessage messageOn = MidiMessage::noteOn(1, noteNumber, velocity); |
| 634 | messageOn.setTimeStamp(noteStart); |
| 635 | track1.addEvent(messageOn); |
| 636 | float noteEnd = (element->mCol + element->mOffset + element->mLength) * ticksPerQuarterNote * |
| 637 | +TheTransport->GetMeasureFraction(mInterval) / TheTransport->GetMeasureFraction(kInterval_4n); |
| 638 | MidiMessage messageOff = MidiMessage::noteOff(1, noteNumber, velocity); |
| 639 | messageOff.setTimeStamp(noteEnd); |
| 640 | track1.addEvent(messageOff); |
| 641 | } |
| 642 | midifile.addTrack(track1); |
| 643 | std::string savePath = chooser.getResult().getFullPathName().toStdString(); |
| 644 | File f(savePath); |
| 645 | FileOutputStream out(f); |
| 646 | midifile.writeTo(out); |
| 647 | } |
| 648 | } |
| 649 | |
| 650 | void NoteCanvas::CheckboxUpdated(Checkbox* checkbox, double time) |
| 651 | { |
nothing calls this directly
no test coverage detected