23#include <core/config.h>
28 #include <QStringConverter>
48 "\\version \"2.16.2\"\n"
52 " (bassdrum default #f -3) ; Kick\n"
53 " (lowoodblock triangle #f 0) ; Stick\n"
54 " (snare default #f 1) ; Snare\n"
55 " (maracas triangle #f -3) ; Hand Clap\n"
56 " (highfloortom default #f -1) ; Tom Low\n"
57 " (hihat cross #f 5) ; Closed HH\n"
58 " (lowtom default #f 2) ; Tom Mid\n"
59 " (pedalhihat cross #f -5) ; Pedal HH\n"
60 " (hightom default #f 3) ; Tom Hi\n"
61 " (openhihat cross \"open\" 5) ; Open HH\n"
62 " (cowbell triangle #f 3) ; Cowbell\n"
63 " (ridecymbal cross #f 4) ; Main Ride\n"
64 " (crashcymbal cross #f 6) ; Main Crash\n"
65 " (ridecymbala cross #f 4) ; Additional Ride\n"
66 " (crashcymbala cross #f 7) ; Additional Crash\n"
83 if ( !group || group->size() == 0 ) {
87 unsigned nSize = group->size();
89 for (
unsigned nPatternList = 0; nPatternList < nSize; nPatternList++ ) {
90 if (
PatternList *pPatternList = ( *group )[ nPatternList ] ) {
97 QFile file( sFilename );
98 if ( ! file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
99 ERRORLOG( QString(
"Unable to open file [%1] for writing" )
104 QTextStream stream( &file );
105#ifdef H2CORE_HAVE_QT6
106 stream.setEncoding( QStringConverter::Utf8 );
108 stream.setCodec( QTextCodec::codecForName(
"UTF-8" ) );
112 stream <<
"\\header {\n";
113 stream <<
" title = \"" <<
m_sName <<
"\"\n";
114 stream <<
" composer = \"" <<
m_sAuthor <<
"\"\n";
115 stream <<
" tagline = \"Generated by Hydrogen " H2CORE_VERSION "\"\n";
118 stream <<
"\\score {\n";
119 stream <<
" \\new DrumStaff <<\n";
120 stream <<
" \\set DrumStaff.drumStyleTable = #(alist->hash-table "
122 stream <<
" \\override Staff.TimeSignature #'style = #'() % Display "
124 stream <<
" \\set Staff.beamExceptions = #'() % Beam "
125 "quavers two by two\n";
126 stream <<
" \\drummode {\n";
127 stream <<
" \\tempo 4 = " <<
static_cast<int>(
m_fBPM ) <<
"\n\n";
138 for (
unsigned nPattern = 0; nPattern < list.
size(); nPattern++ ) {
139 if (
const Pattern *pPattern = list.
get( nPattern ) ) {
147 for (
unsigned nNote = 0; nNote < pattern.
get_length(); nNote++ ) {
148 if ( nNote >= notes.size() ) {
149 notes.push_back( std::vector<std::pair<int, float> >() );
153 if ( !pPatternNotes ) {
157 if (
Note *pNote = it->second ) {
158 int nId = pNote->get_instrument_id();
159 float fVelocity = pNote->get_velocity();
160 notes[ nNote ].push_back( std::make_pair( nId, fVelocity ) );
167 unsigned nSignature = 0;
168 for (
unsigned nMeasure = 0; nMeasure <
m_Measures.size(); nMeasure++ ) {
170 stream <<
"\n % Measure " << nMeasure + 1 <<
"\n";
171 unsigned nNewSignature =
m_Measures[ nMeasure ].size() / 48;
172 if ( nSignature != nNewSignature ) {
173 nSignature = nNewSignature;
174 stream <<
" \\time " << nSignature <<
"/4\n";
180 stream <<
" } \\\\ {\n";
187 unsigned nMeasure )
const {
189 std::vector<int> whiteList;
190 whiteList.push_back( 6 );
191 whiteList.push_back( 7 );
192 whiteList.push_back( 9 );
193 whiteList.push_back( 10 );
194 whiteList.push_back( 11 );
195 whiteList.push_back( 12 );
196 whiteList.push_back( 13 );
197 whiteList.push_back( 14 );
198 whiteList.push_back( 15 );
203 unsigned nMeasure )
const {
204 std::vector<int> whiteList;
205 whiteList.push_back( 0 );
206 whiteList.push_back( 1 );
207 whiteList.push_back( 2 );
208 whiteList.push_back( 3 );
209 whiteList.push_back( 4 );
210 whiteList.push_back( 5 );
211 whiteList.push_back( 8 );
216static const char *
const sNames[] = {
"bd",
"wbl",
"sn",
"mar",
217 "sn",
"tomfh",
"hh",
"toml",
218 "hhp",
"tomh",
"hho",
"cb",
219 "cymr",
"cymc",
"cymra",
"cymca" };
222static void writeNote( QTextStream &stream,
const std::vector<int> ¬es ) {
223 switch ( notes.size() ) {
224 case 0: stream <<
"r";
break;
225 case 1: stream <<
sNames[ notes[ 0 ] ];
break;
228 for (
unsigned i = 0; i < notes.size(); i++ ) {
229 stream <<
sNames[ notes[ i ] ] <<
" ";
237 if ( 48 % duration == 0 ) {
239 if ( duration % 2 ) {
242 stream << 4 * 48 / duration;
244 }
else if ( duration % 3 == 0 && 48 % ( duration * 2 / 3 ) == 0 ) {
246 if ( duration % 2 ) {
249 stream << 4 * 48 / ( duration * 2 / 3 ) <<
".";
253 for (
int pow = 3; pow >= 0; --pow ) {
254 if ( 3 * ( 1 << pow ) < duration ) {
255 stream << 8 * ( 3 - pow ) <<
" r";
265 const std::vector<int> &whiteList )
const {
268 for (
unsigned nStart = 0; nStart < measure.size(); nStart += 48 ) {
269 unsigned lastNote = nStart;
270 for (
unsigned nTime = nStart; nTime < nStart + 48; nTime++ ) {
272 std::vector<int> notes;
273 const std::vector<std::pair<int, float> > &input = measure[ nTime ];
274 for (
unsigned nNote = 0; nNote < input.size(); nNote++ ) {
275 if ( std::find( whiteList.begin(),
277 input[ nNote ].first ) != whiteList.end() ) {
278 notes.push_back( input[ nNote ].first );
283 if ( !notes.empty() || nTime == nStart ) {
285 if ( nTime != nStart ) {
static void writeNote(QTextStream &stream, const std::vector< int > ¬es)
Write duration in LilyPond format, from number of 1/48th of a beat.
static void writeDuration(QTextStream &stream, unsigned duration)
static const char *const sNames[]
Write group of note (may also be a rest or a single note)
static const char * sHeader
#define FOREACH_NOTE_CST_IT_BOUND_LENGTH(_notes, _it, _bound, _pattern)
Iterate over all notes in column _bound in an immutable way if it is contained in _pattern.
QString m_sName
Name of the song.
std::vector< std::vector< std::pair< int, float > > > notes_t
void extractData(const Song &song)
void writeMeasures(QTextStream &stream) const
Write measures in LilyPond format to stream.
static void addPattern(const Pattern &pattern, notes_t ¬es)
QString m_sAuthor
Author of the song.
static void addPatternList(const PatternList &list, notes_t ¬es)
void writeLower(QTextStream &stream, unsigned nMeasure) const
Write lower voice of given measure to stream.
std::vector< notes_t > m_Measures
Representation of the song.
void writeUpper(QTextStream &stream, unsigned nMeasure) const
Write upper voice of given measure to stream.
void writeVoice(QTextStream &stream, unsigned nMeasure, const std::vector< int > &whiteList) const
float m_fBPM
BPM of the song.
void write(const QString &sFilename) const
A note plays an associated instrument with a velocity left and right pan.
PatternList is a collection of patterns.
int size() const
returns the numbers of patterns
Pattern * get(int idx)
get a pattern from the list
Pattern class is a Note container.
int get_length() const
set the denominator of the pattern
const notes_t * get_notes() const
get the virtual pattern set
std::multimap< int, Note * > notes_t
< multimap note type
std::vector< PatternList * > * getPatternGroupVector()
Return a pointer to a vector storing all Pattern present in the Song.
const QString & getName() const
const QString & getAuthor() const
#define H2CORE_VERSION
A concatenation of H2CORE_VERSION_MAJOR, H2CORE_VERSION_MINOR, H2CORE_VERSION_PATCH,...