//----------------------------------------------------------------- // Read Parameters //----------------------------------------------------------------- int CgQUAD::Read(SStream *stream, Tag tag) { if (0 == mgg) gtfo("<rdim> needs mother gauge"); float pm; char txt[128]; switch(tag) { case 'bmap': ReadStrip(stream,txdf); return TAG_READ; case 'rdim': ReadString(txt,128,stream); DecodeRDIM(txt); return TAG_READ; //--- rigth skew ------------ case 'rskw': ReadFloat(&pm,stream); quad[0].VT_Y += pm; quad[3].VT_Y += pm; return TAG_READ; //--- left skew ------------ case 'lskw': ReadFloat(&pm,stream); quad[1].VT_Y += pm; quad[2].VT_Y += pm; return TAG_READ; } WARNINGLOG("Unknown Tag %s",TagToString(tag)); return TAG_IGNORED; }
void InstrumentList::fix_issue_307() { if ( has_all_midi_notes_same() ) { WARNINGLOG( "Same MIDI note assigned to every instrument. Assigning default values." ); set_default_midi_out_notes(); } }
Drumkit* Drumkit::load_from( XMLNode* node, const QString& dk_path ) { QString drumkit_name = node->read_string( "name", "", false, false ); if ( drumkit_name.isEmpty() ) { ERRORLOG( "Drumkit has no name, abort" ); return NULL; } Drumkit* drumkit = new Drumkit(); drumkit->__path = dk_path; drumkit->__name = drumkit_name; drumkit->__author = node->read_string( "author", "undefined author" ); drumkit->__info = node->read_string( "info", "No information available." ); drumkit->__license = node->read_string( "license", "undefined license" ); XMLNode componentListNode = node->firstChildElement( "componentList" ); if ( ! componentListNode.isNull() ) { XMLNode componentNode = componentListNode.firstChildElement( "drumkitComponent" ); while ( ! componentNode.isNull() ) { int id = componentNode.read_int( "id", -1 ); // instrument id QString sName = componentNode.read_string( "name", "" ); // name float fVolume = componentNode.read_float( "volume", 1.0 ); // volume DrumkitComponent* pDrumkitComponent = new DrumkitComponent( id, sName ); pDrumkitComponent->set_volume( fVolume ); drumkit->get_components()->push_back(pDrumkitComponent); componentNode = componentNode.nextSiblingElement( "drumkitComponent" ); } } else { WARNINGLOG( "componentList node not found" ); DrumkitComponent* pDrumkitComponent = new DrumkitComponent( 0, "Main" ); drumkit->get_components()->push_back(pDrumkitComponent); } XMLNode instruments_node = node->firstChildElement( "instrumentList" ); if ( instruments_node.isNull() ) { WARNINGLOG( "instrumentList node not found" ); drumkit->set_instruments( new InstrumentList() ); } else { drumkit->set_instruments( InstrumentList::load_from( &instruments_node, dk_path, drumkit_name ) ); } return drumkit; }
bool LCDCombo::addItem( const QString &text ) { //INFOLOG( "add item" ); if ( text.size() <= size ) { actions.append( pop->addAction( text ) ); return true; } else { WARNINGLOG(QString( "'%1' is > %2").arg( text ).arg( size ) ); return false; } }
void JackOutput::locate( unsigned long nFrame ) { if ( ( Preferences::get_instance() )->m_bJackTransportMode == Preferences::USE_JACK_TRANSPORT /*|| Preferences::get_instance()->m_bJackMasterMode == Preferences::USE_JACK_TIME_MASTER*/ ) { if ( client ) { WARNINGLOG( QString( "Calling jack_transport_locate(%1)" ).arg( nFrame ) ); jack_transport_locate( client, nFrame ); } } else { m_transport.m_nFrames = nFrame; } }
/// Take beat-bar-tick info from the Jack system, and translate it to a new internal frame position and ticksize. void JackOutput::relocateBBT() { Preferences* pPref = Preferences::get_instance(); //wolke if hydrogen is jack time master this is not relevant if ( m_transport.m_status != TransportInfo::ROLLING || pPref->m_bJackMasterMode == Preferences::USE_JACK_TIME_MASTER || ! ( m_JackTransportPos.valid & JackPositionBBT ) ) { WARNINGLOG( "Relocate: Call it off" ); return; } //WARNINGLOG( "Resyncing!" ); INFOLOG( "..." ); Hydrogen * H = Hydrogen::get_instance(); Song * S = H->getSong(); float hydrogen_TPB = ( float )( S->__resolution / m_JackTransportPos.beat_type * 4 ); long bar_ticks = 0; //long beat_ticks = 0; if ( S->get_mode() == Song::SONG_MODE ) { // (Reasonable?) assumption that one pattern is _always_ 1 bar long! bar_ticks = H->getTickForPosition( m_JackTransportPos.bar-1 ); // ignore error NOTE This is wrong -- if loop state is off, transport should just stop ?? if ( bar_ticks < 0 ) bar_ticks = 0; } float hydrogen_ticks_to_locate = bar_ticks + ( m_JackTransportPos.beat-1 ) * hydrogen_TPB + m_JackTransportPos.tick * ( hydrogen_TPB / m_JackTransportPos.ticks_per_beat ); // INFOLOG( QString( "Position from Time Master: BBT [%1,%2,%3]" ) . arg( m_JackTransportPos.bar ) . arg( m_JackTransportPos.beat ) . arg( m_JackTransportPos.tick ) ); // WARNINGLOG( QString(bbt) + " -- Tx/Beat = "+to_string(m_JackTransportPos.ticks_per_beat)+", Meter "+to_string(m_JackTransportPos.beats_per_bar)+"/"+to_string(m_JackTransportPos.beat_type)+" =>tick " + to_string( hydrogen_ticks_to_locate ) ); float fNewTickSize = getSampleRate() * 60.0 / m_transport.m_nBPM / S->__resolution; // not S->m_fBPM !?? if ( fNewTickSize == 0 ) return; // ??!? // NOTE this _should_ prevent audioEngine_process_checkBPMChanged in Hydrogen.cpp from recalculating things. m_transport.m_nTickSize = fNewTickSize; long long nNewFrames = ( long long )( hydrogen_ticks_to_locate * fNewTickSize ); #ifndef JACK_NO_BBT_OFFSET if ( m_JackTransportPos.valid & JackBBTFrameOffset ) nNewFrames += m_JackTransportPos.bbt_offset; #endif m_transport.m_nFrames = nNewFrames; }
void JackAudioDriver::makeTrackOutputs( Song* pSong ) { // Only execute the body of this function if a per-track // creation of the output ports is desired. if( Preferences::get_instance()->m_bJackTrackOuts == false ) return; InstrumentList * pInstruments = pSong->get_instrument_list(); Instrument * pInstr; int nInstruments = ( int ) pInstruments->size(); // create dedicated channel output ports WARNINGLOG( QString( "Creating / renaming %1 ports" ).arg( nInstruments ) ); int nTrackCount = 0; // Resets the `track_map' matrix. for( int i = 0 ; i < MAX_INSTRUMENTS ; i++ ){ for ( int j = 0 ; j < MAX_COMPONENTS ; j++ ){ track_map[i][j] = 0; } } // Creates a new output track or reassigns an existing one for // each component of each instrument and stores the result in // the `track_map'. for ( int n = 0; n <= nInstruments - 1; n++ ) { pInstr = pInstruments->get( n ); for (std::vector<InstrumentComponent*>::iterator it = pInstr->get_components()->begin() ; it != pInstr->get_components()->end(); ++it) { InstrumentComponent* pCompo = *it; setTrackOutput( nTrackCount, pInstr, pCompo, pSong); track_map[pInstr->get_id()][pCompo->get_drumkit_componentID()] = nTrackCount; nTrackCount++; } } // clean up unused ports jack_port_t *p_L, *p_R; for ( int n = nTrackCount; n < track_port_count; n++ ) { p_L = track_output_ports_L[n]; p_R = track_output_ports_R[n]; track_output_ports_L[n] = 0; jack_port_unregister( m_pClient, p_L ); track_output_ports_R[n] = 0; jack_port_unregister( m_pClient, p_R ); } track_port_count = nTrackCount; }
bool LCDCombo::select( int idx, bool emitValueChanged ) { if (active == idx) return false; if (idx < 0 || idx >= actions.size()) { WARNINGLOG(QString("out of index %1 >= %2").arg(idx).arg(actions.size())); return false; } active = idx; display->setText( actions.at( idx )->text() ); if ( emitValueChanged ) emit valueChanged( idx ); return true; }
bool Filesystem::file_copy( const QString& src, const QString& dst, bool overwrite ) { if( file_exists( dst, true ) && !overwrite ) { WARNINGLOG( QString( "do not overwrite %1 with %2 as it already exists" ).arg( dst ).arg( src ) ); return true; } if ( !file_readable( src ) ) { ERRORLOG( QString( "unable to copy %1 to %2, %1 is not readable" ).arg( src ).arg( dst ) ); return false; } if ( !file_writable( dst ) ) { ERRORLOG( QString( "unable to copy %1 to %2, %2 is not writable" ).arg( src ).arg( dst ) ); return false; } INFOLOG( QString( "copy %1 to %2" ).arg( src ).arg( dst ) ); return QFile::copy( src,dst ); }
//---------------------------------------------------------------------- // Read parameters //---------------------------------------------------------------------- int CLoadCell::Read (SStream *stream, Tag tag) { int rc = TAG_IGNORED; switch (tag) { case 'name': // Name of loadout position ReadString (name, 64, stream); name[63] = 0; rc = TAG_READ; break; case 'bPos': // Offset from default center of gravity ReadVector (&bPos, stream); bPos = bPos + mveh->wgh.svh_cofg; bPos.InvertXY(); rc = TAG_READ; break; case 'load': // Default load value in pounds ReadFloat (&load, stream); rc = TAG_READ; break; case 'hiLm': // Maximum load value in pounds ReadFloat (&hiLm, stream); rc = TAG_READ; break; case 'utyp': // UI type ReadString (utyp, 64, stream); rc = TAG_READ; break; } if (rc != TAG_READ) { // Tag was not processed by this object, it is unrecognized WARNINGLOG ("CLoadCell::Read : Unrecognized tag <%s>", TagToString(tag)); } return rc; }
/** * Make sure the number of track outputs match the instruments in @a song , and name the ports. */ void JackOutput::makeTrackOutputs( Song * song ) { /// Disable Track Outputs if( Preferences::get_instance()->m_bJackTrackOuts == false ) return; /// InstrumentList * instruments = song->get_instrument_list(); Instrument * instr; int nInstruments = ( int )instruments->size(); // create dedicated channel output ports WARNINGLOG( QString( "Creating / renaming %1 ports" ).arg( nInstruments ) ); int p_trackCount = 0; for( int i = 0 ; i < MAX_INSTRUMENTS ; i++ ){ for ( int j = 0 ; j < MAX_COMPONENTS ; j++ ){ track_map[i][j] = 0; } } for ( int n = nInstruments - 1; n >= 0; n-- ) { instr = instruments->get( n ); for (std::vector<InstrumentComponent*>::iterator it = instr->get_components()->begin() ; it != instr->get_components()->end(); ++it) { InstrumentComponent* pCompo = *it; setTrackOutput( p_trackCount, instr , pCompo, song); track_map[instr->get_id()][pCompo->get_drumkit_componentID()] = p_trackCount; p_trackCount++; } } // clean up unused ports jack_port_t *p_L, *p_R; for ( int n = p_trackCount; n < track_port_count; n++ ) { p_L = track_output_ports_L[n]; p_R = track_output_ports_R[n]; track_output_ports_L[n] = 0; jack_port_unregister( client, p_L ); track_output_ports_R[n] = 0; jack_port_unregister( client, p_R ); } track_port_count = p_trackCount; }
//---------------------------------------------------------------- // Read all parameters //---------------------------------------------------------------- int VStrip::Read(SStream *str,Tag tag) { char txt[16]; switch (tag) { //---- File name ---------------------- case 'file': case 'bmap': ReadStrip(str); return TAG_READ; //---- POSN position ------------------ case 'posn': ReadPOSN(str); return TAG_READ; //--- PROJ projector ------------------ case 'proj': ReadPROJ(str); return TAG_READ; } TagToString(txt,tag); WARNINGLOG("VStrip: <%s> tag ignored"); return TAG_IGNORED; }
//--------------------------------------------------------------------- // Read all parameters //--------------------------------------------------------------------- int CNeedleMark::Read(SStream *stream, Tag tag) { if (0 == mgg) gtfo("<CNeedleMark: need mother gauge"); switch (tag) { case 'bmap': nedl.SetGauge(mgg); nedl.ReadBMAP(stream); return TAG_READ; //--- rotation center -------------- case 'rotc': nedl.ReadROTC(stream); return TAG_READ; //--- minimum value ---------------- case 'dmin': ReadFloat(&dmin, stream); return TAG_READ; //--- maximum value ---------------- case 'dmax': ReadFloat(&dmax, stream); return TAG_READ; //--- Clamp values ----------------- case 'clmp': ReadFloat(&dmin,stream); ReadFloat(&dmax,stream); return TAG_READ; //--- Current value ---------------- case 'sang': case 'dval': ReadFloat(&dval,stream); SaveValue(dval); return TAG_READ; //--- Knob ------------------------- case 'knob': ReadKNOB(stream); return TAG_READ; } WARNINGLOG("CNeedleMark: tag %s unknowned",TagToString(tag)); return TAG_IGNORED; }
CImageBMP::CImageBMP (const char* bmpFilename) { strncpy (filename, bmpFilename,(PATH_MAX-1)); image = NULL; PODFILE* p = popen (&globals->pfs, filename); if (p != NULL) { // Read header pread (&h, sizeof(SBmpHeader), 1, p); // Read info header pread (&ih, sizeof(SBmpInfoHeader), 1, p); // Read colormap data if (ih.nPlanes == 3) { int cmapSize = ih.nColours * 3; cmap = new unsigned char[cmapSize]; pread (cmap, cmapSize, 1, p); } // Read image data switch (ih.compression) { case 0: // Uncompressed image = new unsigned char[ih.imageSize]; pread (image, ih.imageSize, 1, p); break; default: // Only uncompressed images are currently supported WARNINGLOG ("CImageBMP : Unsupported compression mode %d in %s", ih.compression, filename); } pclose (p); } }
void JackOutput::setBpm( float fBPM ) { WARNINGLOG( QString( "setBpm: %1" ).arg( fBPM ) ); m_transport.m_nBPM = fBPM; }
void JackOutput::updateTransportInfo() { if ( locate_countdown == 1 ) locate( locate_frame ); if ( locate_countdown > 0 ) locate_countdown--; if ( Preferences::get_instance()->m_bJackTransportMode != Preferences::USE_JACK_TRANSPORT ) return; m_JackTransportState = jack_transport_query( client, &m_JackTransportPos ); // update m_transport with jack-transport data switch ( m_JackTransportState ) { case JackTransportStopped: m_transport.m_status = TransportInfo::STOPPED; //infoLog( "[updateTransportInfo] STOPPED - frames: " + to_string(m_transportPos.frame) ); break; case JackTransportRolling: if ( m_transport.m_status != TransportInfo::ROLLING && ( m_JackTransportPos.valid & JackPositionBBT ) ) { must_relocate = 2; //WARNINGLOG( "Jack transport starting: Resyncing in 2 x Buffersize!!" ); } m_transport.m_status = TransportInfo::ROLLING; //infoLog( "[updateTransportInfo] ROLLING - frames: " + to_string(m_transportPos.frame) ); break; case JackTransportStarting: m_transport.m_status = TransportInfo::STOPPED; //infoLog( "[updateTransportInfo] STARTING (stopped) - frames: " + to_string(m_transportPos.frame) ); break; default: ERRORLOG( "Unknown jack transport state" ); } // FIXME // TickSize and BPM Hydrogen * H = Hydrogen::get_instance(); H->setTimelineBpm(); // dlr: fix #168, jack may have re-located us anywhere, check for bpm change every cycle if ( m_JackTransportPos.valid & JackPositionBBT ) { float bpm = ( float )m_JackTransportPos.beats_per_minute; if ( m_transport.m_nBPM != bpm ) { if ( Preferences::get_instance()->m_bJackMasterMode == Preferences::NO_JACK_TIME_MASTER ){ // WARNINGLOG( QString( "Tempo change from jack-transport: %1" ).arg( bpm ) ); m_transport.m_nBPM = bpm; must_relocate = 1; // The tempo change has happened somewhere during the previous cycle; relocate right away. // This commenting out is rude perhaps, but I cant't figure out what this bit is doing. // In any case, setting must_relocate = 1 here causes too many relocates. Jakob Lund /* } else { if ( m_transport.m_status == TransportInfo::STOPPED ) { oldpo = H->getPatternPos(); must_relocate = 1; //changer =1; }*/ } // Hydrogen::get_instance()->setBPM( m_JackTransportPos.beats_per_minute ); // unnecessary, as Song->m_BPM gets updated in audioEngine_process_transport (after calling this function) } } if ( m_transport.m_nFrames + bbt_frame_offset != m_JackTransportPos.frame ) { if ( ( m_JackTransportPos.valid & JackPositionBBT ) && must_relocate == 0 ) { WARNINGLOG( "Frame offset mismatch; triggering resync in 2 cycles" ); must_relocate = 2; } else { if ( Preferences::get_instance()->m_bJackMasterMode == Preferences::NO_JACK_TIME_MASTER ) { // If There's no timebase_master, and audioEngine_process_checkBPMChanged handled a tempo change during last cycle, the offset doesn't match, but hopefully it was calculated correctly: //this perform Jakobs mod in pattern mode, but both m_transport.m_nFrames works with the same result in pattern Mode // in songmode the first case dont work. //so we can remove this "if query" and only use this old mod: m_transport.m_nFrames = H->getHumantimeFrames(); //because to get the songmode we have to add this "H2Core::Hydrogen *m_pEngine" to the header file //if we remove this we also can remove *m_pEngine from header #if 0 // dlr: fix #169, why do we have a different behaviour for SONG_MODE? if ( m_pEngine->getSong()->get_mode() == Song::PATTERN_MODE ){ m_transport.m_nFrames = m_JackTransportPos.frame/* - bbt_frame_offset*/; ///see comment in svn changeset 753 } else { m_transport.m_nFrames = H->getHumantimeFrames(); } #else m_transport.m_nFrames = m_JackTransportPos.frame; bbt_frame_offset = 0; // dlr: stop re-syncing in every cycle when STOPPED #endif // In jack 'slave' mode, if there's no master, the following line is needed to be able to relocate by clicking the song ruler (wierd corner case, but still...) if ( m_transport.m_status == TransportInfo::ROLLING ) H->triggerRelocateDuringPlay(); } else { ///this is experimantal... but it works for the moment... fix me fix :-) wolke // ... will this actually happen? keeping it for now ( jakob lund ) m_transport.m_nFrames = H->getHumantimeFrames(); } } } // humantime fix if ( H->getHumantimeFrames() != m_JackTransportPos.frame ) { H->setHumantimeFrames(m_JackTransportPos.frame); //WARNINGLOG("fix Humantime " + to_string (m_JackTransportPos.frame)); } if ( must_relocate == 1 ) { //WARNINGLOG( "Resyncing!" ); relocateBBT(); if ( m_transport.m_status == TransportInfo::ROLLING ) { H->triggerRelocateDuringPlay(); } } if ( must_relocate > 0 ) must_relocate--; }
void CImageBMP::DrawToSurface (SSurface* surface, int x, int y) { // Check that valid image data exists if (image == NULL) { WARNINGLOG ("CImageBMP::DrawToSurface : NULL image data for %s", filename); return; } int sybase = surface->ySize - y - ih.h; // Copy pixel by pixel unsigned long i, j; unsigned long imageOffset, sx, sy; for (i=0; i<ih.h; i++) { for (j=0; j<ih.w; j++) { switch (ih.nPlanes) { case 1: // 24-bit RGB data { imageOffset = ((i * ih.w) + j) * 3; GLubyte r = image[imageOffset]; GLubyte g = image[imageOffset+1]; GLubyte b = image[imageOffset+2]; GLubyte a = 0xFF; unsigned int rgba = MakeRGBA (r, g, b, a); sx = x+j; sy = sybase+i; if ((sx >= 0) && (sx < (int)surface->xSize) && (sy >= 0) && (sy < (int)surface->ySize)) { unsigned long surfOffset = (sy * surface->xSize) + sx; surface->drawBuffer[surfOffset] = rgba; } } break; case 3: // Pallettized data { imageOffset = (i * ih.w) + j; GLubyte cmapIndex = image[imageOffset]; GLubyte b = cmap[cmapIndex]; GLubyte g = cmap[cmapIndex+1]; GLubyte r = cmap[cmapIndex+2]; GLubyte a = 0xFF; unsigned int rgba = MakeRGBA (r, g, b, a); sx = x+j; sy = sybase+i; if ((sx >= 0) && (sx < (int)surface->xSize) && (sy >= 0) && (sy < (int)surface->ySize)) { unsigned long surfOffset = (sy * surface->xSize) + sx; surface->drawBuffer[surfOffset] = rgba; } } break; } } } }
/// /// Load the preferences file /// void Preferences::loadPreferences( bool bGlobal ) { bool recreate = false; // configuration file must be recreated? QString sPreferencesDirectory; QString sPreferencesFilename; QString sDataDirectory; if ( bGlobal ) { sPreferencesDirectory = DataPath::get_data_path(); sPreferencesFilename = sPreferencesDirectory + "/composite.default.conf"; DEBUGLOG( "Loading preferences file (GLOBAL) [" + sPreferencesFilename + "]" ); } else { sPreferencesFilename = m_sPreferencesFilename; sPreferencesDirectory = m_sPreferencesDirectory; sDataDirectory = QDir::homePath().append( "/.composite/data" ); DEBUGLOG( "Loading preferences file (USER) [" + sPreferencesFilename + "]" ); } // preferences directory exists? QDir prefDir( sPreferencesDirectory ); if ( !prefDir.exists() ) { if ( bGlobal ) { WARNINGLOG( "System configuration directory '" + sPreferencesDirectory + "' not found." ); } else { ERRORLOG( "Configuration directory '" + sPreferencesDirectory + "' not found." ); createPreferencesDirectory(); } } // data directory exists? QDir dataDir( sDataDirectory ); if ( !dataDir.exists() ) { WARNINGLOG( "Data directory not found." ); createDataDirectory(); } // soundLibrary directory exists? QString sDir = sDataDirectory; QString sDrumkitDir; QString sSongDir; QString sPatternDir; DEBUGLOG( "Creating soundLibrary directories in " + sDir ); sDrumkitDir = sDir + "/drumkits"; sSongDir = sDir + "/songs"; sPatternDir = sDir + "/patterns"; QDir drumkitDir( sDrumkitDir ); QDir songDir( sSongDir ); QDir patternDir( sPatternDir ); if ( ! drumkitDir.exists() || ! songDir.exists() || ! patternDir.exists() ) { createSoundLibraryDirectories(); } // pref file exists? std::ifstream input( sPreferencesFilename.toLocal8Bit() , std::ios::in | std::ios::binary ); if ( input ) { // read preferences file QDomDocument doc = LocalFileMng::openXmlDocument( sPreferencesFilename ); QDomNode rootNode = doc.firstChildElement( "hydrogen_preferences" ); if ( !rootNode.isNull() ) { // version QString version = LocalFileMng::readXmlString( rootNode, "version", "" ); if ( version.isEmpty() ) { recreate = true; } //////// GENERAL /////////// //m_sLadspaPath = LocalFileMng::readXmlString( this, rootNode, "ladspaPath", m_sLadspaPath ); m_bShowDevelWarning = LocalFileMng::readXmlBool( rootNode, "showDevelWarning", m_bShowDevelWarning ); restoreLastSong = LocalFileMng::readXmlBool( rootNode, "restoreLastSong", restoreLastSong ); m_bPatternModePlaysSelected = LocalFileMng::readXmlBool( rootNode, "patternModePlaysSelected", TRUE ); hearNewNotes = LocalFileMng::readXmlBool( rootNode, "hearNewNotes", hearNewNotes ); recordEvents = LocalFileMng::readXmlBool( rootNode, "recordEvents", recordEvents ); quantizeEvents = LocalFileMng::readXmlBool( rootNode, "quantizeEvents", quantizeEvents ); QDomNode pRecentUsedSongsNode = rootNode.firstChildElement( "recentUsedSongs" ); if ( !pRecentUsedSongsNode.isNull() ) { QDomElement pSongElement = pRecentUsedSongsNode.firstChildElement( "song" ); while( !pSongElement.isNull() && !pSongElement.text().isEmpty() ){ m_recentFiles.push_back( pSongElement.text() ); pSongElement = pSongElement.nextSiblingElement( "song" ); } } else { DEBUGLOG( "recentUsedSongs node not found" ); } QDomNode pRecentFXNode = rootNode.firstChildElement( "recentlyUsedEffects" ); if ( ! pRecentFXNode.isNull() ) { QDomElement pFXElement = pRecentFXNode.firstChildElement( "FX" ); while ( !pFXElement.isNull() && ! pFXElement.text().isEmpty()) { m_recentFX.push_back( pFXElement.text() ); pFXElement = pFXElement.nextSiblingElement( "FX" ); } } else { DEBUGLOG( "recentlyUsedEffects node not found" ); } sServerList.clear(); QDomNode pServerListNode = rootNode.firstChildElement( "serverList" ); if ( !pServerListNode.isNull() ) { QDomElement pServerElement = pServerListNode.firstChildElement( "server" ); while ( !pServerElement.isNull() && !pServerElement.text().isEmpty() ) { sServerList.push_back( pServerElement.text() ); pServerElement = pServerElement.nextSiblingElement( "server" ); } } else { DEBUGLOG( "serverList node not found" ); } m_patternCategories.clear(); QDomNode pPatternCategoriesNode = rootNode.firstChildElement( "patternCategories" ); if ( !pPatternCategoriesNode.isNull() ) { QDomElement pPatternCategoriesElement = pPatternCategoriesNode.firstChildElement( "categories" ); while ( !pPatternCategoriesElement.isNull() && !pPatternCategoriesElement.text().isEmpty() ) { m_patternCategories.push_back( pPatternCategoriesElement.text() ); pPatternCategoriesElement = pPatternCategoriesElement.nextSiblingElement( "categories" ); } } else { DEBUGLOG( "patternCategories node not found" ); } m_sLastNews = LocalFileMng::readXmlString( rootNode, "lastNews", "-", true ); /////////////// AUDIO ENGINE ////////////// QDomNode audioEngineNode = rootNode.firstChildElement( "audio_engine" ); if ( audioEngineNode.isNull() ) { DEBUGLOG( "audio_engine node not found" ); recreate = true; } else { m_sAudioDriver = LocalFileMng::readXmlString( audioEngineNode, "audio_driver", m_sAudioDriver ); m_bUseMetronome = LocalFileMng::readXmlBool( audioEngineNode, "use_metronome", m_bUseMetronome ); m_fMetronomeVolume = LocalFileMng::readXmlFloat( audioEngineNode, "metronome_volume", 0.5f ); m_nMaxNotes = LocalFileMng::readXmlInt( audioEngineNode, "maxNotes", m_nMaxNotes ); m_nBufferSize = LocalFileMng::readXmlInt( audioEngineNode, "buffer_size", m_nBufferSize ); m_nSampleRate = LocalFileMng::readXmlInt( audioEngineNode, "samplerate", m_nSampleRate ); //// JACK DRIVER //// QDomNode jackDriverNode = audioEngineNode.firstChildElement( "jack_driver" ); if ( jackDriverNode.isNull() ) { DEBUGLOG( "jack_driver node not found" ); recreate = true; } else { m_sJackPortName1 = LocalFileMng::readXmlString( jackDriverNode, "jack_port_name_1", m_sJackPortName1 ); m_sJackPortName2 = LocalFileMng::readXmlString( jackDriverNode, "jack_port_name_2", m_sJackPortName2 ); QString sMode = LocalFileMng::readXmlString( jackDriverNode, "jack_transport_mode", "NO_JACK_TRANSPORT" ); if ( sMode == "NO_JACK_TRANSPORT" ) { m_bJackTransportMode = NO_JACK_TRANSPORT; } else if ( sMode == "USE_JACK_TRANSPORT" ) { m_bJackTransportMode = USE_JACK_TRANSPORT; } //jack time master QString tmMode = LocalFileMng::readXmlString( jackDriverNode, "jack_transport_mode_master", "NO_JACK_TIME_MASTER" ); if ( tmMode == "NO_JACK_TIME_MASTER" ) { m_bJackMasterMode = NO_JACK_TIME_MASTER; } else if ( tmMode == "USE_JACK_TIME_MASTER" ) { m_bJackMasterMode = USE_JACK_TIME_MASTER; } //~ jack time master m_bJackTrackOuts = LocalFileMng::readXmlBool( jackDriverNode, "jack_track_outs", m_bJackTrackOuts ); m_bJackConnectDefaults = LocalFileMng::readXmlBool( jackDriverNode, "jack_connect_defaults", m_bJackConnectDefaults ); m_nJackTrackOutputMode = LocalFileMng::readXmlInt( jackDriverNode, "jack_track_output_mode", m_nJackTrackOutputMode ); } /// MIDI DRIVER /// QDomNode midiDriverNode = audioEngineNode.firstChildElement( "midi_driver" ); if ( midiDriverNode.isNull() ) { DEBUGLOG( "midi_driver node not found" ); recreate = true; } else { m_sMidiDriver = LocalFileMng::readXmlString( midiDriverNode, "driverName", "JackMidi" ); m_sMidiPortName = LocalFileMng::readXmlString( midiDriverNode, "port_name", "None" ); m_nMidiChannelFilter = LocalFileMng::readXmlInt( midiDriverNode, "channel_filter", -1 ); m_bMidiNoteOffIgnore = LocalFileMng::readXmlBool( midiDriverNode, "ignore_note_off", true ); } } /////////////// GUI ////////////// QDomNode guiNode = rootNode.firstChildElement( "gui" ); if ( guiNode.isNull() ) { DEBUGLOG( "gui node not found" ); recreate = true; } else { // QT Style m_sQTStyle = LocalFileMng::readXmlString( guiNode, "QTStyle", m_sQTStyle, true ); // Application font family applicationFontFamily = LocalFileMng::readXmlString( guiNode, "application_font_family", applicationFontFamily ); // Application font pointSize applicationFontPointSize = LocalFileMng::readXmlInt( guiNode, "application_font_pointsize", applicationFontPointSize ); // mixer font family mixerFontFamily = LocalFileMng::readXmlString( guiNode, "mixer_font_family", mixerFontFamily ); // mixer font pointSize mixerFontPointSize = LocalFileMng::readXmlInt( guiNode, "mixer_font_pointsize", mixerFontPointSize ); // Mixer falloff speed mixerFalloffSpeed = LocalFileMng::readXmlFloat( guiNode, "mixer_falloff_speed", 1.1f ); // pattern editor grid resolution m_nPatternEditorGridResolution = LocalFileMng::readXmlInt( guiNode, "patternEditorGridResolution", m_nPatternEditorGridResolution ); m_bPatternEditorUsingTriplets = LocalFileMng::readXmlBool( guiNode, "patternEditorUsingTriplets", m_bPatternEditorUsingTriplets ); m_bShowInstrumentPeaks = LocalFileMng::readXmlBool( guiNode, "showInstrumentPeaks", m_bShowInstrumentPeaks ); m_bIsFXTabVisible = LocalFileMng::readXmlBool( guiNode, "isFXTabVisible", m_bIsFXTabVisible ); // pattern editor grid height m_nPatternEditorGridHeight = LocalFileMng::readXmlInt( guiNode, "patternEditorGridHeight", m_nPatternEditorGridHeight ); // pattern editor grid width m_nPatternEditorGridWidth = LocalFileMng::readXmlInt( guiNode, "patternEditorGridWidth", m_nPatternEditorGridWidth ); // mainForm window properties setMainFormProperties( readWindowProperties( guiNode, "mainForm_properties", mainFormProperties ) ); setMixerProperties( readWindowProperties( guiNode, "mixer_properties", mixerProperties ) ); setPatternEditorProperties( readWindowProperties( guiNode, "patternEditor_properties", patternEditorProperties ) ); setSongEditorProperties( readWindowProperties( guiNode, "songEditor_properties", songEditorProperties ) ); setAudioEngineInfoProperties( readWindowProperties( guiNode, "audioEngineInfo_properties", audioEngineInfoProperties ) ); m_bFollowPlayhead = LocalFileMng::readXmlBool( guiNode, "followPlayhead", true ); //beatcounter QString bcMode = LocalFileMng::readXmlString( guiNode, "bc", "BC_OFF" ); if ( bcMode == "BC_OFF" ) { m_bbc = BC_OFF; } else if ( bcMode == "BC_ON" ) { m_bbc = BC_ON; } QString setPlay = LocalFileMng::readXmlString( guiNode, "setplay", "SET_PLAY_OFF" ); if ( setPlay == "SET_PLAY_OFF" ) { m_mmcsetplay = SET_PLAY_OFF; } else if ( setPlay == "SET_PLAY_ON" ) { m_mmcsetplay = SET_PLAY_ON; } m_countOffset = LocalFileMng::readXmlInt( guiNode, "countoffset", 0 ); m_startOffset = LocalFileMng::readXmlInt( guiNode, "playoffset", 0 ); //~ beatcounter //SoundLibraryPanel expand items __expandSongItem = LocalFileMng::readXmlBool( guiNode, "expandSongItem", __expandSongItem ); __expandPatternItem = LocalFileMng::readXmlBool( guiNode, "expandPatternItem", __expandPatternItem ); for ( unsigned nFX = 0; nFX < MAX_FX; nFX++ ) { QString sNodeName = QString("ladspaFX_properties%1").arg( nFX ); setLadspaProperties( nFX, readWindowProperties( guiNode, sNodeName, m_ladspaProperties[nFX] ) ); } QDomNode pUIStyle = guiNode.firstChildElement( "UI_Style" ); if ( !pUIStyle.isNull() ) { readUIStyle( pUIStyle ); } else { DEBUGLOG( "UI_Style node not found" ); recreate = true; } } /////////////// FILES ////////////// QDomNode filesNode = rootNode.firstChildElement( "files" ); if ( filesNode.isNull() ) { DEBUGLOG( "files node not found" ); recreate = true; } else { // last used song lastSongFilename = LocalFileMng::readXmlString( filesNode, "lastSongFilename", lastSongFilename, true ); m_sDefaultEditor = LocalFileMng::readXmlString( filesNode, "defaulteditor", m_sDefaultEditor, true ); } MidiMap* mM = get_midi_map(); mM->reset(); QDomNode pMidiEventMapNode = rootNode.firstChildElement( "midiEventMap" ); if ( !pMidiEventMapNode.isNull() ) { QDomNode pMidiEventNode = pMidiEventMapNode.firstChildElement( "midiEvent" ); while ( !pMidiEventNode.isNull() ) { if( pMidiEventNode.firstChildElement().nodeValue() == QString("mmcEvent")){ QString event = pMidiEventNode.firstChildElement("mmcEvent").firstChildElement().nodeValue(); QString s_action = pMidiEventNode.firstChildElement("action").firstChildElement().nodeValue(); QString s_param = pMidiEventNode.firstChildElement("parameter").firstChildElement().nodeValue(); Action* pAction = new Action( s_action ); pAction->setParameter1( s_param ); mM->registerMMCEvent(event, pAction); } if( pMidiEventNode.firstChildElement().nodeValue() == QString("noteEvent")){ QString event = pMidiEventNode.firstChildElement("noteEvent").firstChildElement().nodeValue(); QString s_action = pMidiEventNode.firstChildElement("action").firstChildElement().nodeValue(); QString s_param = pMidiEventNode.firstChildElement("parameter").firstChildElement().nodeValue(); QString s_eventParameter = pMidiEventNode.firstChildElement("eventParameter").firstChildElement().nodeValue(); Action* pAction = new Action( s_action ); pAction->setParameter1( s_param ); mM->registerNoteEvent(s_eventParameter.toInt(), pAction); } if( pMidiEventNode.firstChildElement().nodeValue() == QString("ccEvent") ){ QString event = pMidiEventNode.firstChildElement("ccEvent").firstChildElement().nodeValue(); QString s_action = pMidiEventNode.firstChildElement("action").firstChildElement().nodeValue(); QString s_param = pMidiEventNode.firstChildElement("parameter").firstChildElement().nodeValue(); QString s_eventParameter = pMidiEventNode.firstChildElement("eventParameter").firstChildElement().nodeValue(); Action * pAction = new Action( s_action ); pAction->setParameter1( s_param ); mM->registerCCEvent( s_eventParameter.toInt(), pAction ); } pMidiEventNode = pMidiEventNode.nextSiblingElement( "midiEvent" ); } } else { DEBUGLOG( "midiMap node not found" ); } } // rootNode else { DEBUGLOG( "hydrogen_preferences node not found" ); recreate = true; } } else { if ( bGlobal ) { WARNINGLOG( "System configuration file not found." ); } else { WARNINGLOG( "Configuration file not found." ); recreate = true; } } // The preferences file should be recreated? if ( recreate == true ) { WARNINGLOG( "Recreating configuration file." ); savePreferences(); } }
void JackAudioDriver::setBpm( float fBPM ) { WARNINGLOG( QString( "setBpm: %1" ).arg( fBPM ) ); m_transport.m_nBPM = fBPM; }
//---------------------------------------------------------------------- // read parameters //---------------------------------------------------------------------- int CNeedle::Read (SStream *stream, Tag tag) { int pm; double dm; char name[128]; switch (tag) { //--- Vertical amplitude----------- case 'ampv': ReadFloat(&v, stream); return TAG_READ; //--- Horizontal amplitude---------- case 'amph': ReadFloat (&h, stream); return TAG_READ; //--- Starting angle -------------- case 'sang': ReadFloat (&sang, stream); return TAG_READ; //--- ???? ----------------------- case 'dunt': ReadFloat (&dunt, stream); return TAG_READ; //--- Range ---------------------- case 'clmp': ReadFloat(&gmin, stream); ReadFloat(&gmax, stream); return TAG_READ; //--- Offset ?? ------------------ case 'noff': ReadInt (&pm, stream); ReadInt (&pm, stream); return TAG_READ; //--- Vertical adjustment --------- case 'vadj': ReadDouble(&dm, stream); rotn.SetVADJ(dm); return TAG_READ; //--- No what ??? ---------------- case 'noac': return TAG_READ; //--- needle position in gauge --- case 'posn': ReadPOSN(stream); return TAG_READ; //--- needle projector in gauge --- case 'proj': ReadPROJ(stream); return TAG_READ; //--- Rotation center ------------ case 'rotc': ReadROTC(stream); return TAG_READ; //--- Needle center ------------ case 'nctr': ReadNCTR(stream); return TAG_READ; //--- Texture file --------------- case 'file': case 'bmap': rotn.GetTexture(stream); return TAG_READ; //----Table look up ----------------- case 'gtbl': { CDataSearch map(stream); gmap = map.GetTable(); gmap->IncUse(); return TAG_READ; } //---- Message for update ----------- case 'mesg': ReadMessage (&mesg, stream); return TAG_READ; //--- Cursor ----------------------- case 'curs': case 'crsr': cTag = mgg->BindCursor(stream); return TAG_READ; //--- Help message --------------- case 'help': ReadString (help, 64, stream); return TAG_READ; } TagToString(name,tag); WARNINGLOG("CNeedle: %s Tag ignored",name); return TAG_IGNORED; }
void JackAudioDriver::updateTransportInfo() { // The following four lines do only cover the special case of // audioEngine_updateNoteQueue() returning -1 in // audioEngine_process() and triggering an addition relocation // of the transport position to the beginning of the song // using locateInNCycles() to possibly keep synchronization // with Ardour. if ( locate_countdown == 1 ) locate( locate_frame ); if ( locate_countdown > 0 ) locate_countdown--; if ( Preferences::get_instance()->m_bJackTransportMode != Preferences::USE_JACK_TRANSPORT ){ return; } // jack_transport_query() (jack/transport.h) queries the // current transport state and position. If called from the // process thread, the second argument, which is a pointer to // a structure for returning current transport, corresponds to // the first frame of the current cycle and the state returned // is valid for the entire cycle. #m_JackTransportPos->valid // will show which fields contain valid data. If // #m_JackTransportPos is NULL, do not return position // information. m_JackTransportState = jack_transport_query( m_pClient, &m_JackTransportPos ); // WARNINGLOG( QString( "[Jack-Query] state: %1, frame: %2, position bit: %3, bpm: %4" ) // .arg( m_JackTransportState ) // .arg( m_JackTransportPos.frame ) // .arg( m_JackTransportPos.valid ) // .arg( m_JackTransportPos.beats_per_minute ) ); // Update the TransportInfo in m_transport based on the state // returned by jack_transport_query. switch ( m_JackTransportState ) { case JackTransportStopped: // Transport is halted m_transport.m_status = TransportInfo::STOPPED; //INFOLOG( "[updateTransportInfo] STOPPED - frames: " + to_string(m_transportPos.frame) ); break; case JackTransportRolling: // Transport is playing // If the valid member matches the JackPositionBBT // bits, there is a JACK timebase master present // supplying bar, beat, and tick information along // with the plain transport position in frames. We // will use it for re-positioning. But only at the end // of the next cycle, because this timebase master has // to properly initialize its state during this cycle // too. if ( m_transport.m_status != TransportInfo::ROLLING && ( m_JackTransportPos.valid & JackPositionBBT ) ) { must_relocate = 2; //WARNINGLOG( "Jack transport starting: Resyncing in 2 x Buffersize!!" ); } m_transport.m_status = TransportInfo::ROLLING; //INFOLOG( "[updateTransportInfo] ROLLING - frames: " + to_string(m_transportPos.frame) ); break; case JackTransportStarting: // Waiting for sync ready. If // there are slow-sync clients, // this can take more than one // cycle. m_transport.m_status = TransportInfo::STOPPED; //INFOLOG( "[updateTransportInfo] STARTING (stopped) - frames: " + to_string(m_transportPos.frame) ); break; default: ERRORLOG( "Unknown jack transport state" ); } // Updating TickSize and BPM Hydrogen * H = Hydrogen::get_instance(); // JACK may have re-located us anywhere. Therefore, we have to // check for a bpm change every cycle. We will do so by // updating both the global speed of the song, as well as the // fallback speed (H->getNewBpmJTM) with the local tempo at // the current position on the timeline. H->setTimelineBpm(); // Check whether another JACK master is present (the second if // clause won't evaluate to true if Hydrogen itself is the // timebase master) and whether it changed the transport // state. Note that only the JACK timebase master and not // arbitrary clients can do this. If so, the speed is updated // an a relocation according to the bar, beat, and tick // information will be triggered right away. if ( m_JackTransportPos.valid & JackPositionBBT ) { float bpm = ( float )m_JackTransportPos.beats_per_minute; if ( m_transport.m_nBPM != bpm ) { if ( Preferences::get_instance()->m_bJackMasterMode == Preferences::NO_JACK_TIME_MASTER ){ // WARNINGLOG( QString( "Tempo change from jack-transport: %1" ).arg( bpm ) ); m_transport.m_nBPM = bpm; must_relocate = 1; } } } // This clause detects a re-location, which was either // triggered by an user-interaction (e.g. clicking the forward // button or clicking somewhere on the timeline) or by a // different JACK client. if ( m_transport.m_nFrames + bbt_frame_offset != m_JackTransportPos.frame ) { // Whether there is a JACK timebase master registered // but the audio engine was neither (re)started nor a // change in the speed was found beforehand. if ( ( m_JackTransportPos.valid & JackPositionBBT ) && must_relocate == 0 ) { // WARNINGLOG( "Frame offset mismatch; triggering resync in 2 cycles" ); must_relocate = 2; // re-locate at the end of // the next cycle. } else { if ( Preferences::get_instance()->m_bJackMasterMode == Preferences::NO_JACK_TIME_MASTER ) { // Just consider the transport // position as dirty, reassign the // one obtained in the query, and // reset the offset. m_transport.m_nFrames = m_JackTransportPos.frame; bbt_frame_offset = 0; // If not registered as JACK time // master, the following line is // needed to be able to relocate by // clicking the song ruler (wired // corner case, but still...) if ( m_transport.m_status == TransportInfo::ROLLING ) // Setting // H->m_nPatternStartTick = -1 // if in pattern mode. H->triggerRelocateDuringPlay(); } else { // Fallback to the transport position // of the last cycle. m_transport.m_nFrames = H->getHumantimeFrames(); } } } // Only used if Hydrogen is in JACK timebase master // mode. Updated every cycle. if ( H->getHumantimeFrames() != m_JackTransportPos.frame ) { H->setHumantimeFrames(m_JackTransportPos.frame); // WARNINGLOG( QString( "fix Humantime: %1" ).arg( m_JackTransportPos.frame ) ); } // Trigger the re-location based on the information provided // by another JACK timebase master. if ( must_relocate == 1 ) { WARNINGLOG( QString( "Resyncing! bbt_frame_offset: %1" ).arg( bbt_frame_offset ) ); relocateBBT(); if ( m_transport.m_status == TransportInfo::ROLLING ) { // Setting H->m_nPatternStartTick = -1 if in // pattern mode H->triggerRelocateDuringPlay(); } } if ( must_relocate > 0 ) must_relocate--; }
Drumkit* Legacy::load_drumkit( const QString& dk_path ) { if ( version_older_than( 0, 9, 8 ) ) { ERRORLOG( QString( "this code should not be used anymore, it belongs to 0.9.6" ) ); } else { ERRORLOG( QString( "loading drumkit with legacy code" ) ); } XMLDoc doc; if( !doc.read( dk_path ) ) { return 0; } XMLNode root = doc.firstChildElement( "drumkit_info" ); if ( root.isNull() ) { ERRORLOG( "drumkit_info node not found" ); return 0; } QString drumkit_name = root.read_string( "name", "", false, false ); if ( drumkit_name.isEmpty() ) { ERRORLOG( "Drumkit has no name, abort" ); return 0; } Drumkit* drumkit = new Drumkit(); drumkit->set_path( dk_path.left( dk_path.lastIndexOf( "/" ) ) ); drumkit->set_name( drumkit_name ); drumkit->set_author( root.read_string( "author", "undefined author" ) ); drumkit->set_info( root.read_string( "info", "defaultInfo" ) ); drumkit->set_license( root.read_string( "license", "undefined license" ) ); XMLNode instruments_node = root.firstChildElement( "instrumentList" ); if ( instruments_node.isNull() ) { WARNINGLOG( "instrumentList node not found" ); drumkit->set_instruments( new InstrumentList() ); } else { InstrumentList* instruments = new InstrumentList(); XMLNode instrument_node = instruments_node.firstChildElement( "instrument" ); int count = 0; while ( !instrument_node.isNull() ) { count++; if ( count > MAX_INSTRUMENTS ) { ERRORLOG( QString( "instrument count >= %2, stop reading instruments" ).arg( MAX_INSTRUMENTS ) ); break; } Instrument* instrument = 0; int id = instrument_node.read_int( "id", EMPTY_INSTR_ID, false, false ); if ( id!=EMPTY_INSTR_ID ) { instrument = new Instrument( id, instrument_node.read_string( "name", "" ), 0 ); instrument->set_drumkit_name( drumkit_name ); instrument->set_volume( instrument_node.read_float( "volume", 1.0f ) ); instrument->set_muted( instrument_node.read_bool( "isMuted", false ) ); instrument->set_pan_l( instrument_node.read_float( "pan_L", 1.0f ) ); instrument->set_pan_r( instrument_node.read_float( "pan_R", 1.0f ) ); // may not exist, but can't be empty instrument->set_filter_active( instrument_node.read_bool( "filterActive", true, false ) ); instrument->set_filter_cutoff( instrument_node.read_float( "filterCutoff", 1.0f, true, false ) ); instrument->set_filter_resonance( instrument_node.read_float( "filterResonance", 0.0f, true, false ) ); instrument->set_random_pitch_factor( instrument_node.read_float( "randomPitchFactor", 0.0f, true, false ) ); float attack = instrument_node.read_float( "Attack", 0.0f, true, false ); float decay = instrument_node.read_float( "Decay", 0.0f, true, false ); float sustain = instrument_node.read_float( "Sustain", 1.0f, true, false ); float release = instrument_node.read_float( "Release", 1000.0f, true, false ); instrument->set_adsr( new ADSR( attack, decay, sustain, release ) ); instrument->set_gain( instrument_node.read_float( "gain", 1.0f, true, false ) ); instrument->set_mute_group( instrument_node.read_int( "muteGroup", -1, true, false ) ); instrument->set_midi_out_channel( instrument_node.read_int( "midiOutChannel", -1, true, false ) ); instrument->set_midi_out_note( instrument_node.read_int( "midiOutNote", MIDI_MIDDLE_C, true, false ) ); instrument->set_stop_notes( instrument_node.read_bool( "isStopNote", true ,false ) ); instrument->set_hihat_grp( instrument_node.read_int( "isHihat", -1, true ) ); instrument->set_lower_cc( instrument_node.read_int( "lower_cc", 0, true ) ); instrument->set_higher_cc( instrument_node.read_int( "higher_cc", 127, true ) ); for ( int i=0; i<MAX_FX; i++ ) { instrument->set_fx_level( instrument_node.read_float( QString( "FX%1Level" ).arg( i+1 ), 0.0 ), i ); } QDomNode filename_node = instrument_node.firstChildElement( "filename" ); if ( !filename_node.isNull() ) { DEBUGLOG( "Using back compatibility code. filename node found" ); QString sFilename = instrument_node.read_string( "filename", "" ); if( sFilename.isEmpty() ) { ERRORLOG( "filename back compability node is empty" ); } else { Sample* sample = new Sample( dk_path+"/"+sFilename ); bool p_foundMainCompo = false; for (std::vector<DrumkitComponent*>::iterator it = drumkit->get_components()->begin() ; it != drumkit->get_components()->end(); ++it) { DrumkitComponent* existing_compo = *it; if( existing_compo->get_name().compare("Main") == 0) { p_foundMainCompo = true; break; } } if ( !p_foundMainCompo ) { DrumkitComponent* dmCompo = new DrumkitComponent( 0, "Main" ); drumkit->get_components()->push_back(dmCompo); } InstrumentComponent* component = new InstrumentComponent( 0 ); InstrumentLayer* layer = new InstrumentLayer( sample ); component->set_layer( layer, 0 ); instrument->get_components()->push_back( component ); } } else { int n = 0; bool p_foundMainCompo = false; for (std::vector<DrumkitComponent*>::iterator it = drumkit->get_components()->begin() ; it != drumkit->get_components()->end(); ++it) { DrumkitComponent* existing_compo = *it; if( existing_compo->get_name().compare("Main") == 0) { p_foundMainCompo = true; break; } } if ( !p_foundMainCompo ) { DrumkitComponent* dmCompo = new DrumkitComponent( 0, "Main" ); drumkit->get_components()->push_back(dmCompo); } InstrumentComponent* component = new InstrumentComponent( 0 ); XMLNode layer_node = instrument_node.firstChildElement( "layer" ); while ( !layer_node.isNull() ) { if ( n >= MAX_LAYERS ) { ERRORLOG( QString( "n >= MAX_LAYERS (%1)" ).arg( MAX_LAYERS ) ); break; } Sample* sample = new Sample( dk_path+"/"+layer_node.read_string( "filename", "" ) ); InstrumentLayer* layer = new InstrumentLayer( sample ); layer->set_start_velocity( layer_node.read_float( "min", 0.0 ) ); layer->set_end_velocity( layer_node.read_float( "max", 1.0 ) ); layer->set_gain( layer_node.read_float( "gain", 1.0, true, false ) ); layer->set_pitch( layer_node.read_float( "pitch", 0.0, true, false ) ); component->set_layer( layer, n ); n++; layer_node = layer_node.nextSiblingElement( "layer" ); } instrument->get_components()->push_back( component ); } } if( instrument ) { ( *instruments ) << instrument; } else { ERRORLOG( QString( "Empty ID for instrument %1. The drumkit is corrupted. Skipping instrument" ).arg( count ) ); count--; } instrument_node = instrument_node.nextSiblingElement( "instrument" ); } drumkit->set_instruments( instruments ); } return drumkit; }
//-------------------------------------------------------------------------------- // JS NOTE: Add sound as buffer to audiao manager //-------------------------------------------------------------------------------- int CVehicleSound::Read (SStream *stream, Tag tag) { CAudioManager *snd = globals->snd; int rc = TAG_IGNORED; SMessage fmsg; char fint[64]; char fext[64]; switch (tag) { case 'cach': //--- pre-cache sfx files- --------------------- cach = true;; return TAG_READ; //--- Engine sounds ---------------------------- //--- Crash sounds ------------------------------ case 'crsh': ReadCrashSounds(stream); return TAG_READ; //--- Volume for next sound ----------------------- case 'volu': ReadFloat(&volu,stream); return TAG_READ; //--- Loop back sample for next engine sound ----- case 'back': ReadInt(&sample,stream); return TAG_READ; //--- Cranking sound ---------------------------- case 'crkE': // Engine Crank ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetEngineSound('crkE',fext); sample = 0; return TAG_READ; //--- Catching sound ---------------------------- case 'catE': // internal engine catching ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetEngineSound('catE',fext); sample = 0; return TAG_READ; //--- Running sound ----------------------------- case 'runE': // internal engine runing ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetEngineSound('runE',fext); sample = 0; return TAG_READ; //--- short stop sound -------------------------- case 'hltE': // internal engine idle-stop ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetEngineSound('hltE',fext); sample = 0; return TAG_READ; //--- Failing at start up ----------------------- case 'falE': // internal engine stop ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetEngineSound('falE',fext); sample = 0; return TAG_READ; //--- Miss fire sound --------------------------- case 'misE': // internal engine miss fire ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetEngineSound('misE',fext); sample = 0; return TAG_READ; case 'prsi': // Propeller start->idle ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetSound('prsi',fext); return TAG_READ; case 'pris': // Propeller idle->stop ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetSound('pris',fext); return TAG_READ; //--- Wind------------------------------------ case 'wind': // internal wind ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetSound('wind',fext); return TAG_READ; //--- Tires------------------------------------ case 'tire': ReadTireSound(stream); return TAG_READ; //--- Stall horn------------------------------- case 'stal': // internal stall horn ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetSound('stal',fext); return TAG_READ; //--- FLAPS ------------------------------- case 'flap': ReadFlapSound(stream); return TAG_READ; case 'fmsg': // flaps message ReadMessage (&fmsg, stream); rc = TAG_READ; break; //--- Ground------------------------------- case 'grnd': ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetSound('grnd',fext); return TAG_READ; //--- Gear UP------------------------------- case 'geru': ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetSound('geru',fext); return TAG_READ; case 'gerd': //--- Gear Down --------------------------------- ReadString (fint, sizeof (fint) - 1, stream); ReadString (fext, sizeof (fext) - 1, stream); SetSound('gerd',fext); return TAG_READ; //----Outter marker------------------------------- case 'outr': // outer marker ReadString (fext, sizeof (fext) - 1, stream); SetSound('outr',fext); return TAG_READ; //----middle marker------------------------------- case 'midl': // middle marker ReadString (fext, sizeof (fext) - 1, stream); SetSound('midl',fext); return TAG_READ; //--- Inner marker ------------------------------- case 'innr': ReadString (fext, sizeof (fext) - 1, stream); SetSound('innr',fext); return TAG_READ; case 'gyro': //--- gyro sounds --------------------------------- ReadString (fext, sizeof (fext) - 1, stream); SetSound('gyrl',fext); ReadString (fext, sizeof (fext) - 1, stream); SetSound('gyrs',fext); return TAG_READ; case 'gmsg': //---- gyro message ------------------------------ ReadMessage (&fmsg, stream); return TAG_READ; case 'elt_': // elt warning sound ReadString (fext, sizeof (fext) - 1, stream); SetSound('elts',fext); //snd->ReserveSoundBUF('elts',fext,sample); // lc 052310 - return TAG_READ; case 'bend': // ReadFloat (&pMin, stream); ReadFloat (&pMax, stream); return TAG_READ; } if (rc != TAG_READ) { // Tag was not processed by this object, it is unrecognized WARNINGLOG ("CVehicleSound::Read : Unrecognized tag <%s>", TagToString(tag)); } return rc; }
/// Render a note /// Return 0: the note is not ended /// Return 1: the note is ended unsigned Sampler::__render_note( Note* pNote, unsigned nBufferSize, Song* pSong ) { //infoLog( "[renderNote] instr: " + pNote->getInstrument()->m_sName ); assert( pSong ); unsigned int nFramepos; Hydrogen* pEngine = Hydrogen::get_instance(); AudioOutput* audio_output = pEngine->getAudioOutput(); if ( pEngine->getState() == STATE_PLAYING ) { nFramepos = audio_output->m_transport.m_nFrames; } else { // use this to support realtime events when not playing nFramepos = pEngine->getRealtimeFrames(); } Instrument *pInstr = pNote->get_instrument(); if ( !pInstr ) { ERRORLOG( "NULL instrument" ); return 1; } float fLayerGain = 1.0; float fLayerPitch = 0.0; // scelgo il sample da usare in base alla velocity Sample *pSample = NULL; for ( unsigned nLayer = 0; nLayer < MAX_LAYERS; ++nLayer ) { InstrumentLayer *pLayer = pInstr->get_layer( nLayer ); if ( pLayer == NULL ) continue; if ( ( pNote->get_velocity() >= pLayer->get_start_velocity() ) && ( pNote->get_velocity() <= pLayer->get_end_velocity() ) ) { pSample = pLayer->get_sample(); fLayerGain = pLayer->get_gain(); fLayerPitch = pLayer->get_pitch(); break; } } if ( !pSample ) { QString dummy = QString( "NULL sample for instrument %1. Note velocity: %2" ).arg( pInstr->get_name() ).arg( pNote->get_velocity() ); WARNINGLOG( dummy ); return 1; } if ( pNote->get_sample_position() >= pSample->get_frames() ) { WARNINGLOG( "sample position out of bounds. The layer has been resized during note play?" ); return 1; } int noteStartInFrames = ( int ) ( pNote->get_position() * audio_output->m_transport.m_nTickSize ) + pNote->get_humanize_delay(); int nInitialSilence = 0; if ( noteStartInFrames > ( int ) nFramepos ) { // scrivo silenzio prima dell'inizio della nota nInitialSilence = noteStartInFrames - nFramepos; int nFrames = nBufferSize - nInitialSilence; if ( nFrames < 0 ) { int noteStartInFramesNoHumanize = ( int )pNote->get_position() * audio_output->m_transport.m_nTickSize; if ( noteStartInFramesNoHumanize > ( int )( nFramepos + nBufferSize ) ) { // this note is not valid. it's in the future...let's skip it.... ERRORLOG( QString( "Note pos in the future?? Current frames: %1, note frame pos: %2" ).arg( nFramepos ).arg(noteStartInFramesNoHumanize ) ); //pNote->dumpInfo(); return 1; } // delay note execution //INFOLOG( "Delaying note execution. noteStartInFrames: " + to_string( noteStartInFrames ) + ", nFramePos: " + to_string( nFramepos ) ); return 0; } } float cost_L = 1.0f; float cost_R = 1.0f; float cost_track_L = 1.0f; float cost_track_R = 1.0f; if ( pInstr->is_muted() || pSong->__is_muted ) { // is instrument muted? cost_L = 0.0; cost_R = 0.0; if ( Preferences::get_instance()->m_nJackTrackOutputMode == 0 ) { // Post-Fader cost_track_L = 0.0; cost_track_R = 0.0; } } else { // Precompute some values... cost_L = cost_L * pNote->get_velocity(); // note velocity cost_L = cost_L * pNote->get_pan_l(); // note pan cost_L = cost_L * fLayerGain; // layer gain cost_L = cost_L * pInstr->get_pan_l(); // instrument pan cost_L = cost_L * pInstr->get_gain(); // instrument gain cost_L = cost_L * pInstr->get_volume(); // instrument volume if ( Preferences::get_instance()->m_nJackTrackOutputMode == 0 ) { // Post-Fader cost_track_L = cost_L * 2; } cost_L = cost_L * pSong->get_volume(); // song volume cost_L = cost_L * 2; // max pan is 0.5 cost_R = cost_R * pNote->get_velocity(); // note velocity cost_R = cost_R * pNote->get_pan_r(); // note pan cost_R = cost_R * fLayerGain; // layer gain cost_R = cost_R * pInstr->get_pan_r(); // instrument pan cost_R = cost_R * pInstr->get_gain(); // instrument gain cost_R = cost_R * pInstr->get_volume(); // instrument volume if ( Preferences::get_instance()->m_nJackTrackOutputMode == 0 ) { // Post-Fader cost_track_R = cost_R * 2; } cost_R = cost_R * pSong->get_volume(); // song pan cost_R = cost_R * 2; // max pan is 0.5 } // direct track outputs only use velocity if ( Preferences::get_instance()->m_nJackTrackOutputMode == 1 ) { cost_track_L = cost_track_L * pNote->get_velocity(); cost_track_L = cost_track_L * fLayerGain; cost_track_R = cost_track_L; } // Se non devo fare resample (drumkit) posso evitare di utilizzare i float e gestire il tutto in // maniera ottimizzata // constant^12 = 2, so constant = 2^(1/12) = 1.059463. // float nStep = 1.0;1.0594630943593 float fTotalPitch = pNote->get_total_pitch() + fLayerPitch; //_INFOLOG( "total pitch: " + to_string( fTotalPitch ) ); if( ( int )pNote->get_sample_position() == 0 ) { if( Hydrogen::get_instance()->getMidiOutput() != NULL ){ Hydrogen::get_instance()->getMidiOutput()->handleQueueNote( pNote ); } } if ( fTotalPitch == 0.0 && pSample->get_sample_rate() == audio_output->getSampleRate() ) { // NO RESAMPLE return __render_note_no_resample( pSample, pNote, nBufferSize, nInitialSilence, cost_L, cost_R, cost_track_L, cost_track_R, pSong ); } else { // RESAMPLE return __render_note_resample( pSample, pNote, nBufferSize, nInitialSilence, cost_L, cost_R, cost_track_L, cost_track_R, fLayerPitch, pSong ); } }
/// Render a note /// Return false: the note is not ended /// Return true: the note is ended bool Sampler::__render_note( Note* pNote, unsigned nBufferSize, Song* pSong ) { //infoLog( "[renderNote] instr: " + pNote->getInstrument()->m_sName ); assert( pSong ); unsigned int nFramepos; Hydrogen* pEngine = Hydrogen::get_instance(); AudioOutput* audio_output = pEngine->getAudioOutput(); if ( pEngine->getState() == STATE_PLAYING ) { nFramepos = audio_output->m_transport.m_nFrames; } else { // use this to support realtime events when not playing nFramepos = pEngine->getRealtimeFrames(); } Instrument *pInstr = pNote->get_instrument(); if ( !pInstr ) { ERRORLOG( "NULL instrument" ); return 1; } bool nReturnValues [pInstr->get_components()->size()]; for(int i = 0; i < pInstr->get_components()->size(); i++){ nReturnValues[i] = false; } int nReturnValueIndex = 0; int nAlreadySelectedLayer = -1; for (std::vector<InstrumentComponent*>::iterator it = pInstr->get_components()->begin() ; it !=pInstr->get_components()->end(); ++it) { nReturnValues[nReturnValueIndex] = false; InstrumentComponent *pCompo = *it; DrumkitComponent* pMainCompo = pEngine->getSong()->get_component( pCompo->get_drumkit_componentID() ); if( pNote->get_specific_compo_id() != -1 && pNote->get_specific_compo_id() != pCompo->get_drumkit_componentID() ) continue; if( pInstr->is_preview_instrument() || pInstr->is_metronome_instrument()){ pMainCompo = pEngine->getSong()->get_components()->front(); } else { pMainCompo = pEngine->getSong()->get_component( pCompo->get_drumkit_componentID() ); } assert(pMainCompo); float fLayerGain = 1.0; float fLayerPitch = 0.0; // scelgo il sample da usare in base alla velocity Sample *pSample = nullptr; SelectedLayerInfo *pSelectedLayer = pNote->get_layer_selected( pCompo->get_drumkit_componentID() ); if ( !pSelectedLayer ) { QString dummy = QString( "NULL Layer Information for instrument %1. Component: %2" ).arg( pInstr->get_name() ).arg( pCompo->get_drumkit_componentID() ); WARNINGLOG( dummy ); nReturnValues[nReturnValueIndex] = true; continue; } if( pSelectedLayer->SelectedLayer != -1 ) { InstrumentLayer *pLayer = pCompo->get_layer( pSelectedLayer->SelectedLayer ); if( pLayer ) { pSample = pLayer->get_sample(); fLayerGain = pLayer->get_gain(); fLayerPitch = pLayer->get_pitch(); } } else { switch ( pInstr->sample_selection_alg() ) { case Instrument::VELOCITY: for ( unsigned nLayer = 0; nLayer < __maxLayers; ++nLayer ) { InstrumentLayer *pLayer = pCompo->get_layer( nLayer ); if ( pLayer == NULL ) continue; if ( ( pNote->get_velocity() >= pLayer->get_start_velocity() ) && ( pNote->get_velocity() <= pLayer->get_end_velocity() ) ) { pSelectedLayer->SelectedLayer = nLayer; pSample = pLayer->get_sample(); fLayerGain = pLayer->get_gain(); fLayerPitch = pLayer->get_pitch(); break; } } break; case Instrument::RANDOM: if( nAlreadySelectedLayer != -1 ) { InstrumentLayer *pLayer = pCompo->get_layer( nAlreadySelectedLayer ); if ( pLayer != NULL ) { pSelectedLayer->SelectedLayer = nAlreadySelectedLayer; pSample = pLayer->get_sample(); fLayerGain = pLayer->get_gain(); fLayerPitch = pLayer->get_pitch(); } } if( pSample == NULL ) { int __possibleIndex[ __maxLayers ]; int __poundSamples = 0; for ( unsigned nLayer = 0; nLayer < __maxLayers; ++nLayer ) { InstrumentLayer *pLayer = pCompo->get_layer( nLayer ); if ( pLayer == NULL ) continue; if ( ( pNote->get_velocity() >= pLayer->get_start_velocity() ) && ( pNote->get_velocity() <= pLayer->get_end_velocity() ) ) { __possibleIndex[__poundSamples] = nLayer; __poundSamples++; } } if( __poundSamples > 0 ) { nAlreadySelectedLayer = __possibleIndex[rand() % __poundSamples]; pSelectedLayer->SelectedLayer = nAlreadySelectedLayer; InstrumentLayer *pLayer = pCompo->get_layer( nAlreadySelectedLayer ); pSample = pLayer->get_sample(); fLayerGain = pLayer->get_gain(); fLayerPitch = pLayer->get_pitch(); } } break; case Instrument::ROUND_ROBIN: if( nAlreadySelectedLayer != -1 ) { InstrumentLayer *pLayer = pCompo->get_layer( nAlreadySelectedLayer ); if ( pLayer != NULL ) { pSelectedLayer->SelectedLayer = nAlreadySelectedLayer; pSample = pLayer->get_sample(); fLayerGain = pLayer->get_gain(); fLayerPitch = pLayer->get_pitch(); } } if( !pSample ) { int __possibleIndex[ __maxLayers ]; int __foundSamples = 0; float __roundRobinID; for ( unsigned nLayer = 0; nLayer < __maxLayers; ++nLayer ) { InstrumentLayer *pLayer = pCompo->get_layer( nLayer ); if ( pLayer == NULL ) continue; if ( ( pNote->get_velocity() >= pLayer->get_start_velocity() ) && ( pNote->get_velocity() <= pLayer->get_end_velocity() ) ) { __possibleIndex[__foundSamples] = nLayer; __roundRobinID = pLayer->get_start_velocity(); __foundSamples++; } } if( __foundSamples > 0 ) { __roundRobinID = pInstr->get_id() * 10 + __roundRobinID; int p_indexToUse = pSong->get_latest_round_robin(__roundRobinID)+1; if( p_indexToUse > __foundSamples - 1) p_indexToUse = 0; pSong->set_latest_round_robin(__roundRobinID, p_indexToUse); nAlreadySelectedLayer = __possibleIndex[p_indexToUse]; pSelectedLayer->SelectedLayer = nAlreadySelectedLayer; InstrumentLayer *pLayer = pCompo->get_layer( nAlreadySelectedLayer ); pSample = pLayer->get_sample(); fLayerGain = pLayer->get_gain(); fLayerPitch = pLayer->get_pitch(); } } break; } } if ( !pSample ) { QString dummy = QString( "NULL sample for instrument %1. Note velocity: %2" ).arg( pInstr->get_name() ).arg( pNote->get_velocity() ); WARNINGLOG( dummy ); nReturnValues[nReturnValueIndex] = true; continue; } if ( pSelectedLayer->SamplePosition >= pSample->get_frames() ) { WARNINGLOG( "sample position out of bounds. The layer has been resized during note play?" ); nReturnValues[nReturnValueIndex] = true; continue; } int noteStartInFrames = ( int ) ( pNote->get_position() * audio_output->m_transport.m_nTickSize ) + pNote->get_humanize_delay(); int nInitialSilence = 0; if ( noteStartInFrames > ( int ) nFramepos ) { // scrivo silenzio prima dell'inizio della nota nInitialSilence = noteStartInFrames - nFramepos; int nFrames = nBufferSize - nInitialSilence; if ( nFrames < 0 ) { int noteStartInFramesNoHumanize = ( int )pNote->get_position() * audio_output->m_transport.m_nTickSize; if ( noteStartInFramesNoHumanize > ( int )( nFramepos + nBufferSize ) ) { // this note is not valid. it's in the future...let's skip it.... ERRORLOG( QString( "Note pos in the future?? Current frames: %1, note frame pos: %2" ).arg( nFramepos ).arg(noteStartInFramesNoHumanize ) ); //pNote->dumpInfo(); nReturnValues[nReturnValueIndex] = true; continue; } // delay note execution //INFOLOG( "Delaying note execution. noteStartInFrames: " + to_string( noteStartInFrames ) + ", nFramePos: " + to_string( nFramepos ) ); //return 0; continue; } } float cost_L = 1.0f; float cost_R = 1.0f; float cost_track_L = 1.0f; float cost_track_R = 1.0f; assert(pMainCompo); bool isMutedForExport = (pEngine->getIsExportSessionActive() && !pInstr->is_currently_exported()); /* * Is instrument muted? * * This can be the case either if the song, instrument or component is muted or if we're in an * export session and we're doing per-instruments exports, but this instrument is not currently * beeing exported. */ if ( isMutedForExport || pInstr->is_muted() || pSong->__is_muted || pMainCompo->is_muted() ) { cost_L = 0.0; cost_R = 0.0; if ( Preferences::get_instance()->m_nJackTrackOutputMode == 0 ) { // Post-Fader cost_track_L = 0.0; cost_track_R = 0.0; } } else { // Precompute some values... if ( pInstr->get_apply_velocity() ) { cost_L = cost_L * pNote->get_velocity(); // note velocity cost_R = cost_R * pNote->get_velocity(); // note velocity } cost_L = cost_L * pNote->get_pan_l(); // note pan cost_L = cost_L * fLayerGain; // layer gain cost_L = cost_L * pInstr->get_pan_l(); // instrument pan cost_L = cost_L * pInstr->get_gain(); // instrument gain cost_L = cost_L * pCompo->get_gain(); // Component gain cost_L = cost_L * pMainCompo->get_volume(); // Component volument cost_L = cost_L * pInstr->get_volume(); // instrument volume if ( Preferences::get_instance()->m_nJackTrackOutputMode == 0 ) { // Post-Fader cost_track_L = cost_L * 2; } cost_L = cost_L * pSong->get_volume(); // song volume cost_L = cost_L * 2; // max pan is 0.5 cost_R = cost_R * pNote->get_pan_r(); // note pan cost_R = cost_R * fLayerGain; // layer gain cost_R = cost_R * pInstr->get_pan_r(); // instrument pan cost_R = cost_R * pInstr->get_gain(); // instrument gain cost_R = cost_R * pCompo->get_gain(); // Component gain cost_R = cost_R * pMainCompo->get_volume(); // Component volument cost_R = cost_R * pInstr->get_volume(); // instrument volume if ( Preferences::get_instance()->m_nJackTrackOutputMode == 0 ) { // Post-Fader cost_track_R = cost_R * 2; } cost_R = cost_R * pSong->get_volume(); // song pan cost_R = cost_R * 2; // max pan is 0.5 } // direct track outputs only use velocity if ( Preferences::get_instance()->m_nJackTrackOutputMode == 1 ) { cost_track_L = cost_track_L * pNote->get_velocity(); cost_track_L = cost_track_L * fLayerGain; cost_track_R = cost_track_L; } // Se non devo fare resample (drumkit) posso evitare di utilizzare i float e gestire il tutto in // maniera ottimizzata // constant^12 = 2, so constant = 2^(1/12) = 1.059463. // float nStep = 1.0;1.0594630943593 float fTotalPitch = pNote->get_total_pitch() + fLayerPitch; //_INFOLOG( "total pitch: " + to_string( fTotalPitch ) ); if( ( int )pSelectedLayer->SamplePosition == 0 ) { if( Hydrogen::get_instance()->getMidiOutput() != NULL ){ Hydrogen::get_instance()->getMidiOutput()->handleQueueNote( pNote ); } } if ( fTotalPitch == 0.0 && pSample->get_sample_rate() == audio_output->getSampleRate() ) // NO RESAMPLE nReturnValues[nReturnValueIndex] = __render_note_no_resample( pSample, pNote, pSelectedLayer, pCompo, pMainCompo, nBufferSize, nInitialSilence, cost_L, cost_R, cost_track_L, cost_track_R, pSong ); else // RESAMPLE nReturnValues[nReturnValueIndex] = __render_note_resample( pSample, pNote, pSelectedLayer, pCompo, pMainCompo, nBufferSize, nInitialSilence, cost_L, cost_R, cost_track_L, cost_track_R, fLayerPitch, pSong ); nReturnValueIndex++; } for ( unsigned i = 0 ; i < pInstr->get_components()->size() ; i++ ) if ( !nReturnValues[i] ) return false; return true; }
void MidiInput::handleSysexMessage( const MidiMessage& msg ) { /* General MMC message 0 1 2 3 4 5 F0 7F id 6 cmd 247 cmd: 1 stop 2 play 3 Deferred play 4 Fast Forward 5 Rewind 6 Record strobe (punch in) 7 Record exit (punch out) 8 Record ready 9 Pause Goto MMC message 0 1 2 3 4 5 6 7 8 9 10 11 12 240 127 id 6 68 6 1 hr mn sc fr ff 247 */ MidiActionManager * aH = MidiActionManager::get_instance(); MidiMap * mM = MidiMap::get_instance(); Hydrogen *pEngine = Hydrogen::get_instance(); pEngine->lastMidiEventParameter = msg.m_nData1; if ( msg.m_sysexData.size() == 6 ) { if ( ( msg.m_sysexData[0] == 240 ) && ( msg.m_sysexData[1] == 127 ) && //( msg.m_sysexData[2] == 0 ) && ( msg.m_sysexData[3] == 6 ) ) { switch ( msg.m_sysexData[4] ) { case 1: // STOP { pEngine->lastMidiEvent = "MMC_STOP"; aH->handleAction(mM->getMMCAction("MMC_STOP")); break; } case 2: // PLAY { pEngine->lastMidiEvent = "MMC_PLAY"; aH->handleAction(mM->getMMCAction("MMC_PLAY")); break; } case 3: //DEFERRED PLAY { pEngine->lastMidiEvent = "MMC_PLAY"; aH->handleAction(mM->getMMCAction("MMC_PLAY")); break; } case 4: // FAST FWD pEngine->lastMidiEvent = "MMC_FAST_FORWARD"; aH->handleAction(mM->getMMCAction("MMC_FAST_FORWARD")); break; case 5: // REWIND pEngine->lastMidiEvent = "MMC_REWIND"; aH->handleAction(mM->getMMCAction("MMC_REWIND")); break; case 6: // RECORD STROBE (PUNCH IN) pEngine->lastMidiEvent = "MMC_RECORD_STROBE"; aH->handleAction(mM->getMMCAction("MMC_RECORD_STROBE")); break; case 7: // RECORD EXIT (PUNCH OUT) pEngine->lastMidiEvent = "MMC_RECORD_EXIT"; aH->handleAction(mM->getMMCAction("MMC_RECORD_EXIT")); break; case 8: // RECORD READY pEngine->lastMidiEvent = "MMC_RECORD_READY"; aH->handleAction(mM->getMMCAction("MMC_RECORD_READY")); break; case 9: //PAUSE pEngine->lastMidiEvent = "MMC_PAUSE"; aH->handleAction(mM->getMMCAction("MMC_PAUSE")); break; default: WARNINGLOG( "Unknown MMC Command" ); // midiDump( buf, nBytes ); } } } else if ( msg.m_sysexData.size() == 13 ) { ERRORLOG( "MMC GOTO Message not implemented yet" ); // midiDump( buf, nBytes ); //int id = buf[2]; int hr = msg.m_sysexData[7]; int mn = msg.m_sysexData[8]; int sc = msg.m_sysexData[9]; int fr = msg.m_sysexData[10]; int ff = msg.m_sysexData[11]; char tmp[200]; sprintf( tmp, "[handleSysexMessage] GOTO %d:%d:%d:%d:%d", hr, mn, sc, fr, ff ); INFOLOG( tmp ); } else { // sysex dump QString sDump; char tmpChar[64]; for ( int i = 0; i < ( int )msg.m_sysexData.size(); ++i ) { sprintf( tmpChar, "%X ", ( int )msg.m_sysexData[ i ] ); sDump += tmpChar; } WARNINGLOG( QString( "Unknown SysEx message: (%1) [%2]" ).arg( msg.m_sysexData.size() ).arg( sDump ) ); } }
void MidiInput::handleMidiMessage( const MidiMessage& msg ) { EventQueue::get_instance()->push_event( EVENT_MIDI_ACTIVITY, -1 ); // infoLog( "[handleMidiMessage]" ); // infoLog( "[handleMidiMessage] channel: " + to_string( msg.m_nChannel ) ); // infoLog( "[handleMidiMessage] val1: " + to_string( msg.m_nData1 ) ); // infoLog( "[handleMidiMessage] val2: " + to_string( msg.m_nData2 ) ); // midi channel filter for all messages bool bIsChannelValid = true; if ( Preferences::get_instance()->m_nMidiChannelFilter != -1 ) { bIsChannelValid = ( msg.m_nChannel == Preferences::get_instance()->m_nMidiChannelFilter); } // exclude all midi channel filter independent messages int type = msg.m_type; if(MidiMessage::SYSEX == type || MidiMessage::SYSTEM_EXCLUSIVE == type || MidiMessage::START == type || MidiMessage::CONTINUE == type || MidiMessage::STOP == type || MidiMessage::SONG_POS == type || MidiMessage::QUARTER_FRAME == type ){ bIsChannelValid =true; } if(!bIsChannelValid) return; switch ( type ) { case MidiMessage::SYSEX: handleSysexMessage( msg ); break; case MidiMessage::NOTE_ON: handleNoteOnMessage( msg ); break; case MidiMessage::NOTE_OFF: handleNoteOffMessage( msg ); break; case MidiMessage::POLYPHONIC_KEY_PRESSURE: ERRORLOG( "POLYPHONIC_KEY_PRESSURE event not handled yet" ); break; case MidiMessage::CONTROL_CHANGE: INFOLOG( QString( "[handleMidiMessage] CONTROL_CHANGE Parameter: %1, Value: %2").arg( msg.m_nData1 ).arg( msg.m_nData2 ) ); handleControlChangeMessage( msg ); break; case MidiMessage::PROGRAM_CHANGE: INFOLOG( QString( "[handleMidiMessage] PROGRAM_CHANGE event, seting next pattern to %1" ).arg( msg.m_nData1 ) ); Hydrogen::get_instance()->sequencer_setNextPattern(msg.m_nData1, false, false); break; case MidiMessage::CHANNEL_PRESSURE: ERRORLOG( "CHANNEL_PRESSURE event not handled yet" ); break; case MidiMessage::PITCH_WHEEL: ERRORLOG( "PITCH_WHEEL event not handled yet" ); break; case MidiMessage::SYSTEM_EXCLUSIVE: ERRORLOG( "SYSTEM_EXCLUSIVE event not handled yet" ); break; case MidiMessage::START: INFOLOG( "START event" ); if ( Hydrogen::get_instance()->getState() != STATE_PLAYING ) { Hydrogen::get_instance()->sequencer_play(); } break; case MidiMessage::CONTINUE: ERRORLOG( "CONTINUE event not handled yet" ); break; case MidiMessage::STOP: INFOLOG( "STOP event" ); if ( Hydrogen::get_instance()->getState() == STATE_PLAYING ) { Hydrogen::get_instance()->sequencer_stop(); } break; case MidiMessage::SONG_POS: ERRORLOG( "SONG_POS event not handled yet" ); break; case MidiMessage::QUARTER_FRAME: WARNINGLOG( "QUARTER_FRAME event not handled yet" ); break; case MidiMessage::UNKNOWN: ERRORLOG( "Unknown midi message" ); break; default: ERRORLOG( QString( "unhandled midi message type: %1" ).arg( msg.m_type ) ); } }
int LocalFileMng::savePattern( Song *song , const QString& drumkit_name, int selectedpattern , const QString& patternname, const QString& realpatternname, int mode) { //int mode = 1 save, int mode = 2 save as // INSTRUMENT NODE Instrument *instr = song->get_instrument_list()->get( 0 ); assert( instr ); Pattern *pat = song->get_pattern_list()->get( selectedpattern ); QString sPatternDir = Preferences::get_instance()->getDataDirectory() + "patterns/" + drumkit_name; INFOLOG( "[savePattern]" + sPatternDir ); // check if the directory exists QDir dir( sPatternDir ); QDir dirPattern( sPatternDir ); if ( !dir.exists() ) { dir.mkdir( sPatternDir );// create the drumkit directory } QString sPatternXmlFilename; // create the drumkit.xml file switch ( mode ){ case 1: //save sPatternXmlFilename = sPatternDir + "/" + QString( patternname + QString( ".h2pattern" )); break; case 2: //save as sPatternXmlFilename = patternname; break; case 3: //"save" but overwrite a existing pattern. mode 3 disable the last file exist check sPatternXmlFilename = sPatternDir + "/" + QString( patternname + QString( ".h2pattern" )); break; case 4: //tmp pattern needed by undo/redo sPatternXmlFilename = patternname; default: WARNINGLOG( "Pattern Save unknown status"); break; } //test if the file exists QFile testfile( sPatternXmlFilename ); if ( testfile.exists() && mode == 1) return 1; QDomDocument doc; QDomProcessingInstruction header = doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\""); doc.appendChild( header ); QDomNode rootNode = doc.createElement( "drumkit_pattern" ); //LIB_ID just in work to get better usability //writeXmlString( &rootNode, "LIB_ID", "in_work" ); writeXmlString( rootNode, "pattern_for_drumkit", drumkit_name ); writeXmlString( rootNode, "author", song->get_author() ); writeXmlString( rootNode, "license", song->get_license() ); // pattern QDomNode patternNode = doc.createElement( "pattern" ); writeXmlString( patternNode, "pattern_name", realpatternname ); QString category; if ( pat->get_category().isEmpty() ) category = "No category"; else category = pat->get_category(); writeXmlString( patternNode, "info", pat->get_info() ); writeXmlString( patternNode, "category", category ); writeXmlString( patternNode, "size", QString("%1").arg( pat->get_length() ) ); QDomNode noteListNode = doc.createElement( "noteList" ); const Pattern::notes_t* notes = pat->get_notes(); FOREACH_NOTE_CST_IT_BEGIN_END(notes,it) { Note *pNote = it->second; assert( pNote ); QDomNode noteNode = doc.createElement( "note" ); writeXmlString( noteNode, "position", QString("%1").arg( pNote->get_position() ) ); writeXmlString( noteNode, "leadlag", QString("%1").arg( pNote->get_lead_lag() ) ); writeXmlString( noteNode, "velocity", QString("%1").arg( pNote->get_velocity() ) ); writeXmlString( noteNode, "pan_L", QString("%1").arg( pNote->get_pan_l() ) ); writeXmlString( noteNode, "pan_R", QString("%1").arg( pNote->get_pan_r() ) ); writeXmlString( noteNode, "pitch", QString("%1").arg( pNote->get_pitch() ) ); writeXmlString( noteNode, "key", pNote->key_to_string() ); writeXmlString( noteNode, "length", QString("%1").arg( pNote->get_length() ) ); writeXmlString( noteNode, "instrument", QString("%1").arg( pNote->get_instrument()->get_id() ) ); noteListNode.appendChild( noteNode ); }