void XmTrackerPattern::getNote(uint16_t row, uint8_t channel, struct XmTrackerNote ¬e) { if (!pattern.nRows) { LOG((LGPFX"Error: No pattern loaded, can't load notes!\n")); ASSERT(pattern.nRows); resetNote(note); return; } if (row >= pattern.nRows) { LOG((LGPFX"Error: Row %u is larger than pattern (%u rows)\n", row, pattern.nRows)); ASSERT(row < pattern.nRows); resetNote(note); return; } if (channel >= song->nChannels) { LOG((LGPFX"Error: Channel %u is too large (song contains %u channels)\n", channel, song->nChannels)); ASSERT(channel < song->nChannels); resetNote(note); return; } /* This is not an error condition, but can happen on an empty pattern. * Indicated by 64 rows, but no pData/dataSize. */ if (!pattern.dataSize || !pattern.pData) { // TODO: test empty patterns LOG((LGPFX"Notice: Emitting empty note\n")); resetNote(note); return; } uint32_t noteIndex = row * song->nChannels + channel; if (noteIndex < noteOffset) { /* This happens on fxLoopPattern, but isn't terribly efficient. * Composers should avoid if reasonable (Workaround: more patterns). */ if (row * song->nChannels + channel > 0) LOG((LGPFX"Notice: Had to seek(0) to get to note %u\n", row * song->nChannels + channel)); offset = 0; noteOffset = 0; } else if (noteIndex > noteOffset) { /* This happens on fxPatternBreak, but isn't very efficient. * Composers should avoid if reasonable (Workaround: more patterns). */ LOG((LGPFX"Notice: Reading past %u notes to get to target\n", row * song->nChannels + channel - noteOffset)); } while(noteIndex >= noteOffset) nextNote(note); }
CMindMapDtNoteTool::CMindMapDtNoteTool(QWidget *parent) : CDiagramTool(parent), m_noteEditor(NULL), m_noteSpriteMenu(NULL) { ui = new Ui::CMindMapDtNoteTool(); ui->setupUi(this); m_noteEditor = new CMindMapUiNoteEditor(NULL); m_noteEditor->hide(); m_noteSpriteMenu = new CMindMapNoteSpriteMenu(NULL); // register the menu to the manager CMindMapMenuManager::instance()->setNodeSpriteMenu(CMindMapNode::Note, m_noteSpriteMenu); connect(ui->m_btnAddNote, SIGNAL(clicked()), this, SLOT(onShowNoteEditor())); connect(ui->m_btnDropNote, SIGNAL(clicked()), this, SLOT(onDeleteNote())); connect(m_noteEditor, SIGNAL(deleteNote()), this, SLOT(onDeleteNote())); connect(m_noteEditor, SIGNAL(resetNote(QString)), this, SLOT(onResetNote(QString))); connect(m_noteSpriteMenu, SIGNAL(deleteNote()), this, SLOT(onDeleteNote())); connect(m_noteSpriteMenu, SIGNAL(showNoteEditor()), this, SLOT(onShowNoteEditor())); }
void XmTrackerPattern::nextNote(struct XmTrackerNote ¬e) { /* The maximum amount of space a note can take up is 6 bytes, if the note * is encoded and still conatains all the members of XmTrackerNote. * In practice a note should never take more than 5 bytes, since that is * the space an uncompressed note occupies, and stir verifies that patterns * are encoded as efficiently as possible. */ uint8_t noteData[6]; SvmMemory::VirtAddr va = pattern.pData + offset; if(!SvmMemory::copyROData(ref, noteData, va, sizeof(noteData))) { LOG((LGPFX"Error: Could not copy %p (length %lu)!\n", (void *)va, (long unsigned)sizeof(noteData))); ASSERT(false); resetNote(note); return; } uint8_t *buf = noteData; if (*buf & 0x80) { uint8_t enc = *(buf++); // encoded note note.note = enc & (1 << 0) ? *(buf++) : kNoNote; note.instrument = enc & (1 << 1) ? *(buf++) : kNoInstrument; note.volumeColumnByte = enc & (1 << 2) ? *(buf++) : kNoVolume; note.effectType = enc & (1 << 3) ? *(buf++) : kNoEffect; note.effectParam = enc & (1 << 4) ? *(buf++) : kNoParam; // If enc & 0x60 > 0 the pattern is likely corrupt, but follow Postel's Law. offset += Intrinsic::POPCOUNT(enc & 0x9F); } else { // unencoded note note.note = *(buf++); note.instrument = *(buf++); note.volumeColumnByte = *(buf++); note.effectType = *(buf++); note.effectParam = *(buf++); offset += 5; } noteOffset++; // If the effect parameter is set but the effect was not, it was intended to be an arpeggio (effect 0) if (note.effectType == kNoEffect && note.effectParam != kNoParam) { note.effectType = 0; } // Clean up note if (note.note > kNoteOff && note.note != kNoNote) note.note = kNoNote; if (note.note == 0) note.note = kNoNote; // Clean up instrument if (note.instrument > 0 && note.instrument <= song->nInstruments) note.instrument--; else note.instrument = kNoInstrument; // Clean up volume if (note.volumeColumnByte <= 0x0F) note.volumeColumnByte = 0; if (note.volumeColumnByte >= 0x51 && note.volumeColumnByte <= 0x5F) note.volumeColumnByte = kNoVolume; if (note.volumeColumnByte >= 0xC0 && note.volumeColumnByte <= 0xEF) note.volumeColumnByte = 0; if (note.effectType != kNoEffect && note.effectParam == kNoParam) note.effectParam = 0; /* Users of this API should be able to check if a note is real * with < kNoteOff (97), so ensure it is never 0. */ if (!note.note) { ASSERT(note.note); note.note = kNoNote; } }