Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Humanizer #627

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified data/img/gray/mixerPanel/masterMixerline_background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 32 additions & 5 deletions src/core/include/hydrogen/basics/song.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,38 @@ class Song : public H2Core::Object
__humanize_velocity_value = value;
}

float get_swing_factor()
{
return __swing_factor;
int get_humanize_time_color()
{
return __humanize_time_color;
}
void set_humanize_time_color( int color )
{
// Colors:
// 0 - white noise
// 1 - pink noise
if ( color < 0 | color > 1 ){
ERRORLOG( "Wrong color code in the humanizer. Resetting it to white noise" );
color = 0;
}
__humanize_time_color = color;
}
void set_swing_factor( float factor );

int get_humanize_velocity_color()
{
return __humanize_velocity_color;
}
void set_humanize_velocity_color( int color )
{
// Colors:
// 0 - white noise
// 1 - pink noise
if ( color < 0 | color > 1 ){
ERRORLOG( "Wrong color code in the humanizer. Resetting it to white noise" );
color = 0;
}
__humanize_velocity_color = color;
}

SongMode get_mode()
{
return __song_mode;
Expand Down Expand Up @@ -295,7 +321,8 @@ class Song : public H2Core::Object
bool __is_loop_enabled;
float __humanize_time_value;
float __humanize_velocity_value;
float __swing_factor;
int __humanize_time_color;
int __humanize_velocity_color;
bool __is_modified;
std::map< float, int> __latest_round_robins;
SongMode __song_mode;
Expand Down
5 changes: 2 additions & 3 deletions src/core/include/hydrogen/hydrogen.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
#define STATE_READY 4 // Ready to process audio
#define STATE_PLAYING 5 // Currently playing a sequence.

inline int randomValue( int max );

// ***************** //

namespace H2Core
{
Expand Down Expand Up @@ -275,7 +276,6 @@ class Hydrogen : public H2Core::Object
Song::SongMode m_oldEngineMode;
bool m_bOldLoopEnabled;
bool m_bExportSessionIsActive;


//Timline information
Timeline* m_pTimeline;
Expand All @@ -285,7 +285,6 @@ class Hydrogen : public H2Core::Object

std::list<Instrument*> __instrument_death_row; /// Deleting instruments too soon leads to potential crashes.


/// Private constructor
Hydrogen();

Expand Down
154 changes: 154 additions & 0 deletions src/core/include/hydrogen/randomizer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* Hydrogen
* Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
* Humanizer
* Copyright(c) 2018 by Philipp Müller [thegreatwhiteshark@googlemail.com]
*
* http://www.hydrogen-music.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/

#ifndef RANDOMIZER_H
#define RANDOMIZER_H

#include <cassert>
#include <cmath>

#define PI ( 3.1415926536d )
/**
* Number of white noise sources to approximate a 1/f spectrum in the
* pink() function.
*/
#define PINK_USED_ROWS ( 12 )
/**
* Maximum number of independent white noise sources to be used in
* pink().
*/
#define PINK_MAX_ROWS ( 30 )
/**
* Number of bits used in the output of the pink() function.
*/
#define PINK_BITS ( 24 )
/**
* How much bits less then the 32 bit long integer does the output of
* the pink() function have.
*/
#define PINK_SHIFT ( ( sizeof( long )* 8 ) - PINK_BITS )

namespace H2Core {

/**
* @brief Used to generate all random numbers used within the humanizer.
*
* Since not only Gaussian white noise, with increments perfectly
* independent from each other, but also noise of different colors
* will be use, this object provides a state of the random number
* generator. This state is required to draw the next, correlated
* number and should not be shared between different instruments.
*/
class Randomizer {
public:
// Constructor and destructor
Randomizer();
// Functions to create and retrieve an instance of the
// Randomizer within Hydrogen.
static Randomizer* create_instance();
static Randomizer* get_instance();
//
////////////// White uniform noise ///////////////////////////
// Composed generator with a multiplicative linear
// congruential generator as the outer method and a 64-bit
// Xorshift method as the inner one.
unsigned long long int white_uniform_int64();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use Doxygen for "documentation" comments.

// Double precision version of the white noise generator.
double white_uniform();
//////////////////////////////////////////////////////////////
//
////////////////////// Gaussian white noise //////////////////
// Box-Muller transformation. The resulting Gaussian random
// variable will be of mean 0 and of standard deviation
// `standardDeviation'.
double white_gaussian( double standardDeviation );
//////////////////////////////////////////////////////////////
//
/////////////////////////// Pink noise ///////////////////////
// Actual algorithm producing the pink noise.
float pink( float scale );
//////////////////////////////////////////////////////////////

private:
static Randomizer* __instance;
////////////// White uniform noise ///////////////////////////
/**
* Internal state of the white uniform random number
* generator.
*/
unsigned long long int uniformStateInt64;
//////////////////////////////////////////////////////////////
//
////////////////////// Gaussian white noise //////////////////
/**
* @brief Auxiliary variable storing an addition Gaussian
* white number.
*
* The white_gaussian() function generates two
* Gaussian-distributed variables out of two uniformly
* distributed ones. One will be returned and the other stored
* in this variable to be returned during the next call.
*/
double gaussianSecondVariable;
//////////////////////////////////////////////////////////////
//
/////////////////////////// Pink noise ///////////////////////
/**
* Array containing the PINK_MAX_ROWS independent white
* noise sources in the pink() function.
*/
long rowsPink[ PINK_MAX_ROWS ];
/**
* Variable holding the sum over all independent white noise
* sources (used for optimization purposes) in the pink()
* function.
*/
long runningSumPink;
/**
* Internal time unit of the pink() function.
*/
int indexPink;
/**
* Determines the maximum possible value of `indexPink'.
*/
int indexMaskPink;
/**
* Biggest possible value generated by the pink noise source
* pink().
*/
long maxValuePink;
/**
* Normalization constant to transform the result of the
* pink() function of type long into float and in the range of
* -1.0 to +1.0.
*/
float normalizationPink;
//////////////////////////////////////////////////////////////
};

};

#endif /* RANDOMIZER_H */


24 changes: 9 additions & 15 deletions src/core/src/basics/song.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ Song::Song( const QString& name, const QString& author, float bpm, float volume
, __is_loop_enabled( false )
, __humanize_time_value( 0.0 )
, __humanize_velocity_value( 0.0 )
, __swing_factor( 0.0 )
// Colors: 0 - white noise; 1 - pink noise
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use enum or, preferably, enum class for storing noise color.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I also like the idea of using an enum class to store the color of the noise instead of just an integer value. But the color needs to be saved to the .h2song file. Therefore I would vote against using such a class since this would require some additional overhead in converting it both in the MixerLine and the LocalFileMng/Song instance.

What do you think?

, __humanize_time_color( 0 )
, __humanize_velocity_color( 0 )
, __song_mode( PATTERN_MODE )
, __components( NULL )
, __playback_track_enabled( false )
Expand Down Expand Up @@ -157,7 +159,8 @@ Song* Song::get_default_song()
song->set_mode( Song::PATTERN_MODE );
song->set_humanize_time_value( 0.0 );
song->set_humanize_velocity_value( 0.0 );
song->set_swing_factor( 0.0 );
song->set_humanize_time_color( 0 );
song->set_humanize_velocity_color( 0 );

InstrumentList* pList = new InstrumentList();
Instrument* pNewInstr = new Instrument( EMPTY_INSTR_ID, "New instrument" );
Expand Down Expand Up @@ -213,17 +216,6 @@ DrumkitComponent* Song::get_component( int ID )
}


void Song::set_swing_factor( float factor )
{
if ( factor < 0.0 ) {
factor = 0.0;
} else if ( factor > 1.0 ) {
factor = 1.0;
}

__swing_factor = factor;
}

void Song::set_is_modified(bool is_modified)
{
bool Notify = false;
Expand Down Expand Up @@ -446,7 +438,8 @@ Song* SongReader::readSong( const QString& filename )

float fHumanizeTimeValue = LocalFileMng::readXmlFloat( songNode, "humanize_time", 0.0 );
float fHumanizeVelocityValue = LocalFileMng::readXmlFloat( songNode, "humanize_velocity", 0.0 );
float fSwingFactor = LocalFileMng::readXmlFloat( songNode, "swing_factor", 0.0 );
int iHumanizeTimeColor = LocalFileMng::readXmlInt( songNode, "humanize_time_color", 0 );
int iHumanizeVelocityColor = LocalFileMng::readXmlInt( songNode, "humanize_velocity_color", 0 );

song = new Song( sName, sAuthor, fBpm, fVolume );
song->set_metronome_volume( fMetronomeVolume );
Expand All @@ -456,7 +449,8 @@ Song* SongReader::readSong( const QString& filename )
song->set_mode( nMode );
song->set_humanize_time_value( fHumanizeTimeValue );
song->set_humanize_velocity_value( fHumanizeVelocityValue );
song->set_swing_factor( fSwingFactor );
song->set_humanize_time_color( iHumanizeTimeColor );
song->set_humanize_velocity_color( iHumanizeVelocityColor );
song->set_playback_track_filename( sPlaybackTrack );
song->set_playback_track_enabled( bPlaybackTrackEnabled );
song->set_playback_track_volume( fPlaybackTrackVolume );
Expand Down
Loading