hydrogen 1.2.3
SmfEvent.cpp
Go to the documentation of this file.
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 * Copyright(c) 2008-2024 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22
23#include <core/Smf/SMFEvent.h>
24#include <core/Timehelper.h>
25
26namespace H2Core
27{
28
30
31void SMFBuffer::writeByte( short int nByte )
32{
33// infoLog( "[writeByte] " + to_string( nByte ) );
34 m_buffer.push_back( nByte );
35}
36
37
38
39void SMFBuffer::writeWord( int nVal )
40{
41// infoLog( "writeWord" );
42 writeByte( nVal >> 8 );
43 writeByte( nVal );
44}
45
46
47
48void SMFBuffer::writeDWord( long nVal )
49{
50 writeByte( nVal >> 24 );
51 writeByte( nVal >> 16 );
52 writeByte( nVal >> 8 );
53 writeByte( nVal );
54}
55
56
57
58void SMFBuffer::writeString( const QString& sMsg )
59{
60// infoLog( "writeString" );
61 writeVarLen( sMsg.length() );
62
63 for ( int i = 0; i < sMsg.length(); i++ ) {
64 writeByte( sMsg.toLocal8Bit().at(i) );
65 }
66}
67
68
69
70void SMFBuffer::writeVarLen( long value )
71{
72// infoLog( "[writeVarLen]" );
73 long buffer;
74 buffer = value & 0x7f;
75 while ( ( value >>= 7 ) > 0 ) {
76 INFOLOG( "." );
77 buffer <<= 8;
78 buffer |= 0x80;
79 buffer += ( value & 0x7f );
80 }
81
82 while ( true ) {
83// putc( buffer, outfile );
84 writeByte( ( char )buffer );
85 if ( buffer & 0x80 ) {
86 buffer >>= 8;
87 } else {
88 break;
89 }
90 }
91}
92
93
94// ::::::::::::::::::
95
96SMFTrackNameMetaEvent::SMFTrackNameMetaEvent( const QString& sTrackName, unsigned nTicks )
97 : SMFEvent( nTicks )
98 , m_sTrackName( sTrackName )
99{
100 // it's always at the start of the song
101 m_nDeltaTime = 0;
102}
103
104
106{
107 SMFBuffer buf;
109 buf.writeByte( 0xFF );
110 buf.writeByte( TRACK_NAME );
112
113 return buf.getBuffer();
114}
115
116// ::::::::::::::::::
117
118SMFSetTempoMetaEvent::SMFSetTempoMetaEvent( float fBPM, unsigned nTicks )
119 : SMFEvent( nTicks )
120 , m_fBPM( fBPM )
121{
122 // it's always at the start of the song
123 m_nDeltaTime = 0;
124}
125
126
128{
129 SMFBuffer buf;
130 long msPerBeat;
131
132 msPerBeat = long( 60000000 / m_fBPM ); // 60 seconds * mills \ BPM
133
135 buf.writeByte( 0xFF );
136 buf.writeByte( SET_TEMPO );
137 buf.writeByte( 0x03 ); // Length
138
139 buf.writeByte( msPerBeat >> 16 );
140 buf.writeByte( msPerBeat >> 8 );
141 buf.writeByte( msPerBeat );
142
143 return buf.getBuffer();
144}
145
146// ::::::::::::::::::
147
148SMFCopyRightNoticeMetaEvent::SMFCopyRightNoticeMetaEvent( const QString& sAuthor, unsigned nTicks )
149 : SMFEvent( nTicks )
150 , m_sAuthor( sAuthor )
151{
152 // it's always at the start of the song
153 m_nDeltaTime = 0;
154}
155
156
158{
159 SMFBuffer buf;
160 QString sCopyRightString;
161
162 time_t now = time(nullptr);
163 tm *ltm = localtime(&now); // Extract the local system time.
164
165 // Construct the copyright string in the form "(C) [Author] [CurrentYear]"
166 sCopyRightString.append("(C) "); // Start with the copyright symbol and a separator space.
167 sCopyRightString.append( m_sAuthor ); // add the author
168 sCopyRightString.append(" "); // add a separator space
169 sCopyRightString.append( QString::number( 1900 + ltm->tm_year, 10 ) ); // and finish with the year.
170
172 buf.writeByte( 0xFF );
174 buf.writeString( sCopyRightString );
175
176 return buf.getBuffer();
177}
178
179// ::::::::::::::::::
180
181SMFTimeSignatureMetaEvent::SMFTimeSignatureMetaEvent( unsigned nBeats, unsigned nNote , unsigned nMTPMC , unsigned nTSNP24 , unsigned nTicks )
182 : SMFEvent( nTicks )
183 , m_nBeats( nBeats )
184 , m_nNote( nNote )
185 , m_nMTPMC( nMTPMC )
186 , m_nTSNP24( nTSNP24 )
187 , m_nTicks( nTicks )
188
189{
190 // it's always at the start of the song
191 m_nDeltaTime = 0;
192}
193
194
196{
197 SMFBuffer buf;
198
199 unsigned nBeatsCopy = m_nNote , Note2Log = 0; // Copy Nbeats as the process to generate Note2Log alters the value.
200
201 while (nBeatsCopy >>= 1) ++Note2Log; // Generate a log to base 2 of the note value, so 8 (as in 6/8) becomes 3
202
204 buf.writeByte( 0xFF );
206 buf.writeByte( 0x04 ); // Event length in bytes.
207 buf.writeByte( m_nBeats ); // Top line of time signature, eg 6 for 6/8 time
208 buf.writeByte( Note2Log ); // Bottom line of time signature expressed as Log2 of the Note value.
209 buf.writeByte( m_nMTPMC ); // MIDI Ticks per Metronome click, normally 24 ( i.e. each quarter note ).
210 buf.writeByte( m_nTSNP24 ); // Thirty Second Notes ( as in 1/32 ) per 24 MIDI clocks, normally 8.
211
212 return buf.getBuffer();
213}
214
215// :::::::::::::
216
217
218SMFEvent::SMFEvent( unsigned nTicks )
219 : Object( )
220 , m_nTicks( nTicks )
221 , m_nDeltaTime( -1 )
222{
223 //infoLog( "INIT" );
224}
225
226
227
229{
230 //infoLog( "DESTROY" );
231}
232
233
234// ::::::::::::::
235
236SMFNoteOnEvent::SMFNoteOnEvent( unsigned nTicks, int nChannel, int nPitch, int nVelocity )
237 : SMFEvent( nTicks )
238 , m_nChannel( nChannel )
239 , m_nPitch( nPitch )
240 , m_nVelocity( nVelocity )
241{
242 if ( nChannel >= 16 ) {
243 ERRORLOG( QString( "nChannel >= 16! nChannel=%1" ).arg( nChannel ) );
244 }
245}
246
247
248
249std::vector<char> SMFNoteOnEvent::getBuffer()
250{
251 SMFBuffer buf;
254 buf.writeByte( m_nPitch );
255 buf.writeByte( m_nVelocity );
256
257 return buf.getBuffer();
258}
259
260
261// :::::::::::
262
263
264SMFNoteOffEvent::SMFNoteOffEvent( unsigned nTicks, int nChannel, int nPitch, int nVelocity )
265 : SMFEvent( nTicks )
266 , m_nChannel( nChannel )
267 , m_nPitch( nPitch )
268 , m_nVelocity( nVelocity )
269{
270 if ( nChannel >= 16 ) {
271 ERRORLOG( QString( "nChannel >= 16! nChannel=%1" ).arg( nChannel ) );
272 }
273}
274
275
276
277std::vector<char> SMFNoteOffEvent::getBuffer()
278{
279 SMFBuffer buf;
282 buf.writeByte( m_nPitch );
283 buf.writeByte( m_nVelocity );
284
285 return buf.getBuffer();
286}
287
288};
#define INFOLOG(x)
Definition Object.h:237
#define ERRORLOG(x)
Definition Object.h:239
std::vector< char > getBuffer()
Definition SMFEvent.h:37
void writeByte(short int nByte)
Definition SmfEvent.cpp:31
std::vector< char > m_buffer
Definition SMFEvent.h:47
void writeVarLen(long nVal)
Definition SmfEvent.cpp:70
void writeString(const QString &sMsg)
Definition SmfEvent.cpp:58
void writeDWord(long nVal)
Definition SmfEvent.cpp:48
void writeWord(int nVal)
Definition SmfEvent.cpp:39
virtual std::vector< char > getBuffer() override
Definition SmfEvent.cpp:157
SMFCopyRightNoticeMetaEvent(const QString &sAuthor, unsigned nDeltaTime)
Definition SmfEvent.cpp:148
virtual ~SMFEvent()
Definition SmfEvent.cpp:228
SMFEvent(unsigned nTicks)
Definition SmfEvent.cpp:218
virtual std::vector< char > getBuffer() override
Definition SmfEvent.cpp:277
SMFNoteOffEvent(unsigned nTicks, int nChannel, int nPitch, int nVelocity)
Definition SmfEvent.cpp:264
virtual std::vector< char > getBuffer() override
Definition SmfEvent.cpp:249
SMFNoteOnEvent(unsigned nTicks, int nChannel, int nPitch, int nVelocity)
Definition SmfEvent.cpp:236
virtual std::vector< char > getBuffer() override
Definition SmfEvent.cpp:127
SMFSetTempoMetaEvent(float fBPM, unsigned nDeltaTime)
Definition SmfEvent.cpp:118
SMFTimeSignatureMetaEvent(unsigned nBeats, unsigned nNote, unsigned nMTPMC, unsigned nTSNP24, unsigned nTicks)
Definition SmfEvent.cpp:181
virtual std::vector< char > getBuffer() override
Definition SmfEvent.cpp:195
SMFTrackNameMetaEvent(const QString &sTrackName, unsigned nDeltaTime)
Definition SmfEvent.cpp:96
virtual std::vector< char > getBuffer() override
Definition SmfEvent.cpp:105
@ NOTE_ON
Definition SMFEvent.h:56
@ NOTE_OFF
Definition SMFEvent.h:55
@ TIME_SIGNATURE
Definition SMFEvent.h:72
@ SET_TEMPO
Definition SMFEvent.h:71
@ COPYRIGHT_NOTICE
Definition SMFEvent.h:64
@ TRACK_NAME
Definition SMFEvent.h:65