Esempio n. 1
0
//-----------------------------------------------------------------
//	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;
}
Esempio n. 2
0
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();
	}
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
	}
}
Esempio n. 5
0
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;
	}
}
Esempio n. 6
0
/// 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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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 );
}
Esempio n. 10
0
//----------------------------------------------------------------------
//  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;
}
Esempio n. 11
0
/**
 * 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;
}
Esempio n. 12
0
//----------------------------------------------------------------
//  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;
}
Esempio n. 13
0
//---------------------------------------------------------------------
//  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;
}
Esempio n. 14
0
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);
  }
}
Esempio n. 15
0
void JackOutput::setBpm( float fBPM )
{
	WARNINGLOG( QString( "setBpm: %1" ).arg( fBPM ) );
	m_transport.m_nBPM = fBPM;
}
Esempio n. 16
0
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--;
}
Esempio n. 17
0
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;
      }
    }
  }
}
Esempio n. 18
0
///
/// 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;
}
Esempio n. 20
0
//----------------------------------------------------------------------
//  read parameters
//----------------------------------------------------------------------
int CNeedle::Read (SStream *stream, Tag tag)
{ int pm;
  double dm;
  char name[128];

  switch (tag) {
    //--- Vertical amplitude-----------
    case 'ampv':
      ReadFloat(&ampv, stream);
      return TAG_READ;
    //--- Horizontal amplitude----------
    case 'amph':
      ReadFloat (&amph, 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--;
}
Esempio n. 22
0
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;
}
Esempio n. 23
0
//--------------------------------------------------------------------------------
//  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;
}
Esempio n. 24
0
/// 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 );
	}
}
Esempio n. 25
0
/// 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;
}
Esempio n. 26
0
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 ) );
	}
}
Esempio n. 27
0
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 ) );
        }
}
Esempio n. 28
0
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 );
	}