-
Notifications
You must be signed in to change notification settings - Fork 172
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
base: master
Are you sure you want to change the base?
Humanizer #627
Changes from all commits
e88c117
240eefe
2e0feb6
378274e
33b87ae
2d83ea4
7cbc822
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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(); | ||
// 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 */ | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could use enum or, preferably, enum class for storing noise color. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 ) | ||
|
@@ -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" ); | ||
|
@@ -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; | ||
|
@@ -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 ); | ||
|
@@ -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 ); | ||
|
There was a problem hiding this comment.
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.