76 WARNINGLOG( QString(
"Provided pitch out of bound [%1;%2]. Rounding to nearest allowed value." )
101 "filename",
"",
false,
false, bSilent );
102 QString sFilePath = sFileName;
108 ! sFileName.startsWith(
"/" ) ) {
110#ifdef H2CORE_HAVE_OSC
111 if ( pHydrogen->isUnderSessionManagement() ) {
122 if ( sFileName.left( 2 ) ==
"./" ||
123 sFileName.left( 2 ) ==
".\\" ) {
128 sFileName.right( sFileName.size() - 1 );
131 sFilePath = sDrumkitPath +
"/" + sFileName;
135 sFilePath = sDrumkitPath +
"/" + sFileName;
138 sFilePath = sDrumkitPath +
"/" + sFileName;
149 ( sFileName.contains(
"/" ) || sFileName.contains(
"\\" ) ) ) {
153 const QString sFileNameCleaned = QString( sFileName )
154 .replace(
"\\",
"/" ).replace(
"//",
"/" );
156 const auto pathSegments = sFileNameCleaned.split(
"/" );
157 if ( pathSegments.size() > 2 ) {
158 const auto sDrumkitSampleSegment = QString(
"%1/%2" )
159 .arg( pathSegments[ pathSegments.size() - 2 ] )
160 .arg( pathSegments[ pathSegments.size() - 1 ] );
162 const auto drumkitFolders = QStringList() <<
164 for (
const auto& ssFolder : drumkitFolders ) {
165 const auto sNewPath = QString(
"%1/%2" )
166 .arg( ssFolder ).arg( sDrumkitSampleSegment );
168 WARNINGLOG( QString(
"File [%1] does not exist. Loading similar file [%2] instead." )
169 .arg( sFileName ).arg( sNewPath ) );
170 sFilePath = sNewPath;
177 std::shared_ptr<Sample> pSample =
nullptr;
179 pSample = std::make_shared<Sample>( sFilePath, drumkitLicense );
185 bool bIsModified = pNode->
read_bool(
"ismodified",
false,
true,
false,
true );
186 pSample->set_is_modified( bIsModified );
194 loops.
count = pNode->
read_int(
"loops", 0,
false,
false, bSilent );
196 pSample->set_loops( loops );
199 rubberband.
use = pNode->
read_int(
"userubber", 0,
false,
false, bSilent );
200 rubberband.
divider = pNode->
read_float(
"rubberdivider", 0.0,
false,
false, bSilent );
201 rubberband.
c_settings = pNode->
read_int(
"rubberCsettings", 1,
false,
false, bSilent );
202 rubberband.
pitch = pNode->
read_float(
"rubberPitch", 0.0,
false,
false, bSilent );
206 m_rubberBandCLIexecutable ) ) {
207 rubberband.
use =
false;
209 pSample->set_rubberband( rubberband );
215 XMLNode volumeNode = pNode->firstChildElement(
"volume" );
216 while ( ! volumeNode.isNull() ) {
217 pt.
frame = volumeNode.
read_int(
"volume-position", 0,
false,
false, bSilent );
218 pt.
value = volumeNode.
read_int(
"volume-value", 0,
false,
false , bSilent);
219 velocityEnvelope.push_back( pt );
220 volumeNode = volumeNode.nextSiblingElement(
"volume" );
222 pSample->set_velocity_envelope( velocityEnvelope );
225 XMLNode panNode = pNode->firstChildElement(
"pan" );
226 while ( ! panNode.isNull() ) {
227 pt.
frame = panNode.
read_int(
"pan-position", 0,
false,
false, bSilent );
228 pt.
value = panNode.
read_int(
"pan-value", 0,
false,
false, bSilent );
229 panEnvelope.push_back( pt );
230 panNode = panNode.nextSiblingElement(
"pan" );
232 pSample->set_pan_envelope( panEnvelope );
236 WARNINGLOG( QString(
"Sample file [%1] does not exist at [%2]" )
237 .arg( sFileName ).arg( sFilePath ) );
240 auto pLayer = std::make_shared<InstrumentLayer>( pSample );
241 pLayer->set_start_velocity( pNode->
read_float(
"min", 0.0,
242 true,
true, bSilent ) );
243 pLayer->set_end_velocity( pNode->
read_float(
"max", 1.0,
244 true,
true, bSilent ) );
245 pLayer->set_gain( pNode->
read_float(
"gain", 1.0,
246 true,
false, bSilent ) );
247 pLayer->set_pitch( pNode->
read_float(
"pitch", 0.0,
248 true,
false, bSilent ) );
256 if ( pSample ==
nullptr ) {
257 ERRORLOG(
"No sample associated with layer. Skipping it" );
266 if ( pHydrogen->isUnderSessionManagement() ) {
272 if ( pSample->get_raw_filepath().startsWith(
'.' ) ) {
273 sFileName = pSample->get_raw_filepath();
284 sFileName = pSample->get_filename();
294 layer_node.
write_bool(
"ismodified", pSample->get_is_modified() );
295 layer_node.
write_string(
"smode", pSample->get_loop_mode_string() );
304 layer_node.
write_int(
"userubber",
static_cast<int>(rubberband.
use) );
309 for (
const auto& velocity : *pSample->get_velocity_envelope() ) {
311 volumeNode.
write_int(
"volume-position", velocity.frame );
312 volumeNode.
write_int(
"volume-value", velocity.value );
315 for (
const auto& pan : *pSample->get_pan_envelope() ) {
317 panNode.
write_int(
"pan-position", pan.frame );
318 panNode.
write_int(
"pan-value", pan.value );
327 sOutput = QString(
"%1[InstrumentLayer]\n" ).arg( sPrefix )
328 .append( QString(
"%1%2gain: %3\n" ).arg( sPrefix ).arg( s ).arg(
__gain ) )
329 .append( QString(
"%1%2pitch: %3\n" ).arg( sPrefix ).arg( s ).arg(
__pitch ) )
330 .append( QString(
"%1%2start_velocity: %3\n" ).arg( sPrefix ).arg( s ).arg(
__start_velocity ) )
331 .append( QString(
"%1%2end_velocity: %3\n" ).arg( sPrefix ).arg( s ).arg(
__end_velocity ) );
333 sOutput.append( QString(
"%1" )
334 .arg(
__sample->toQString( sPrefix + s, bShort ) ) );
336 sOutput.append( QString(
"%1%2sample: nullptr\n" ).arg( sPrefix ).arg( s ) );
340 sOutput = QString(
"[InstrumentLayer]" )
341 .append( QString(
" gain: %1" ).arg(
__gain ) )
342 .append( QString(
", pitch: %1" ).arg(
__pitch ) )
346 sOutput.append( QString(
", sample: %1\n" ).arg(
__sample->get_filepath() ) );
348 sOutput.append( QString(
", sample: nullptr\n" ) );
static QString sPrintIndention
String used to format the debugging string output of some core classes.
A container for a sample, being able to apply modifications on it.
static QString usr_drumkits_dir()
returns user drumkits path
static QString sys_drumkits_dir()
returns system drumkits path
static QString prepare_sample_path(const QString &sFilePath)
Returns the basename if the given path is under an existing user or system drumkit path,...
static bool file_exists(const QString &path, bool silent=false)
returns true if the given path is an existing regular file
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
float get_gain() const
get the gain of the layer
void set_pitch(float pitch)
set the pitch of the layer
static std::shared_ptr< InstrumentLayer > load_from(XMLNode *pNode, const QString &sDrumkitPath, const License &drumkitLicense=License(), bool bSilent=false)
load an instrument layer from an XMLNode
float __start_velocity
the start velocity of the sample, 0.0 by default
float get_pitch() const
get the pitch of the layer
float __gain
ratio between the input sample and the output signal, 1.0 by default
float __pitch
the frequency of the sample, 0.0 by default which means output pitch is the same as input pitch
std::shared_ptr< Sample > __sample
the underlaying sample
void save_to(XMLNode *node, bool bFull=false)
save the instrument layer within the given XMLNode
InstrumentLayer(std::shared_ptr< Sample > sample)
constructor
~InstrumentLayer()
destructor
QString toQString(const QString &sPrefix="", bool bShort=true) const override
Formatted string version for debugging purposes.
std::shared_ptr< Sample > get_sample() const
get the sample of the layer
float get_start_velocity() const
get the start velocity of the layer
void load_sample(float fBpm=120)
Calls the H2Core::Sample::load() member function of __sample.
float __end_velocity
the end velocity of the sample, 1.0 by default
void set_sample(std::shared_ptr< Sample > sample)
set the sample of the layer
float get_end_velocity() const
get the end velocity of the layer
static constexpr float fPitchMin
Minimum support pitch value.
static constexpr float fPitchMax
Maximum support pitch value.
Wrapper class to help Hydrogen deal with the license information specified in a drumkit.
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
set of loop configuration flags
int end_frame
the frame index where to end the new sample to
int start_frame
the frame index where to start the new sample from
LoopMode mode
one of the possible loop modes
int count
the counts of loops to apply
int loop_frame
the frame index where to start the loop from
set of rubberband configuration flags
int c_settings
TODO should be crispness, see rubberband -h.
float divider
TODO should be ratio : desired time ratio.
bool use
is rubberband enabled
static Loops::LoopMode parse_loop_mode(const QString &string)
parse the given string and rturn the corresponding loop_mode
std::vector< EnvelopePoint > VelocityEnvelope
define the type used to store velocity envelope points
XMLNode is a subclass of QDomNode with read and write values methods.
int read_int(const QString &node, int default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads an integer stored into a child node
bool read_bool(const QString &node, bool default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a boolean stored into a child node
QString read_string(const QString &node, const QString &default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a string stored into a child node
float read_float(const QString &node, float default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a float stored into a child node
void write_float(const QString &node, const float value)
write a float into a child node
XMLNode createNode(const QString &name)
create a new XMLNode that has to be appended into de XMLDoc
void write_string(const QString &node, const QString &value)
write a string into a child node
void write_bool(const QString &node, const bool value)
write a boolean into a child node
void write_int(const QString &node, const int value)
write an integer into a child node
static NsmClient * get_instance()
QString getSessionFolderPath() const