hydrogen 1.2.6
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-2025 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( char nChar ) {
32 m_buffer.push_back( nChar );
33}
34
35
36
37void SMFBuffer::writeWord( int nVal ) {
38 writeByte( nVal >> 8 );
39 writeByte( nVal );
40}
41
42
43
44void SMFBuffer::writeDWord( long nVal ) {
45 writeByte( nVal >> 24 );
46 writeByte( nVal >> 16 );
47 writeByte( nVal >> 8 );
48 writeByte( nVal );
49}
50
51
52
53void SMFBuffer::writeString( const QString& sMsg ) {
54 writeVarLen( sMsg.length() );
55
56 m_buffer.append( sMsg.toUtf8() );
57}
58
59
60
61void SMFBuffer::writeVarLen( long value ) {
62 long buffer;
63 buffer = value & 0x7f;
64 while ( ( value >>= 7 ) > 0 ) {
65 INFOLOG( "." );
66 buffer <<= 8;
67 buffer |= 0x80;
68 buffer += ( value & 0x7f );
69 }
70
71 while ( true ) {
72// putc( buffer, outfile );
73 writeByte( ( char )buffer );
74 if ( buffer & 0x80 ) {
75 buffer >>= 8;
76 } else {
77 break;
78 }
79 }
80}
81
82
83// ::::::::::::::::::
84
85SMFTrackNameMetaEvent::SMFTrackNameMetaEvent( const QString& sTrackName, unsigned nTicks )
86 : SMFEvent( nTicks )
87 , m_sTrackName( sTrackName )
88{
89 // it's always at the start of the song
90 m_nDeltaTime = 0;
91}
92
93
95{
96 SMFBuffer buf;
98 buf.writeByte( 0xFF );
99 buf.writeByte( TRACK_NAME );
101
102 return buf.getBuffer();
103}
104
105// ::::::::::::::::::
106
107SMFSetTempoMetaEvent::SMFSetTempoMetaEvent( float fBPM, unsigned nTicks )
108 : SMFEvent( nTicks )
109 , m_fBPM( fBPM )
110{
111 // it's always at the start of the song
112 m_nDeltaTime = 0;
113}
114
115
117{
118 SMFBuffer buf;
119 long msPerBeat;
120
121 msPerBeat = long( 60000000 / m_fBPM ); // 60 seconds * mills \ BPM
122
124 buf.writeByte( 0xFF );
125 buf.writeByte( SET_TEMPO );
126 buf.writeByte( 0x03 ); // Length
127
128 buf.writeByte( msPerBeat >> 16 );
129 buf.writeByte( msPerBeat >> 8 );
130 buf.writeByte( msPerBeat );
131
132 return buf.getBuffer();
133}
134
135// ::::::::::::::::::
136
137SMFCopyRightNoticeMetaEvent::SMFCopyRightNoticeMetaEvent( const QString& sAuthor, unsigned nTicks )
138 : SMFEvent( nTicks )
139 , m_sAuthor( sAuthor )
140{
141 // it's always at the start of the song
142 m_nDeltaTime = 0;
143}
144
145
147{
148 SMFBuffer buf;
149 QString sCopyRightString;
150
151 time_t now = time(nullptr);
152 tm *ltm = localtime(&now); // Extract the local system time.
153
154 // Construct the copyright string in the form "(C) [Author] [CurrentYear]"
155 sCopyRightString.append("(C) "); // Start with the copyright symbol and a separator space.
156 sCopyRightString.append( m_sAuthor ); // add the author
157 sCopyRightString.append(" "); // add a separator space
158 sCopyRightString.append( QString::number( 1900 + ltm->tm_year, 10 ) ); // and finish with the year.
159
161 buf.writeByte( 0xFF );
163 buf.writeString( sCopyRightString );
164
165 return buf.getBuffer();
166}
167
168// ::::::::::::::::::
169
170SMFTimeSignatureMetaEvent::SMFTimeSignatureMetaEvent( unsigned nBeats, unsigned nNote , unsigned nMTPMC , unsigned nTSNP24 , unsigned nTicks )
171 : SMFEvent( nTicks )
172 , m_nBeats( nBeats )
173 , m_nNote( nNote )
174 , m_nMTPMC( nMTPMC )
175 , m_nTSNP24( nTSNP24 )
176 , m_nTicks( nTicks )
177
178{
179 // it's always at the start of the song
180 m_nDeltaTime = 0;
181}
182
183
185{
186 SMFBuffer buf;
187
188 unsigned nBeatsCopy = m_nNote , Note2Log = 0; // Copy Nbeats as the process to generate Note2Log alters the value.
189
190 while (nBeatsCopy >>= 1) ++Note2Log; // Generate a log to base 2 of the note value, so 8 (as in 6/8) becomes 3
191
193 buf.writeByte( 0xFF );
195 buf.writeByte( 0x04 ); // Event length in bytes.
196 buf.writeByte( m_nBeats ); // Top line of time signature, eg 6 for 6/8 time
197 buf.writeByte( Note2Log ); // Bottom line of time signature expressed as Log2 of the Note value.
198 buf.writeByte( m_nMTPMC ); // MIDI Ticks per Metronome click, normally 24 ( i.e. each quarter note ).
199 buf.writeByte( m_nTSNP24 ); // Thirty Second Notes ( as in 1/32 ) per 24 MIDI clocks, normally 8.
200
201 return buf.getBuffer();
202}
203
204// :::::::::::::
205
206
207SMFEvent::SMFEvent( unsigned nTicks )
208 : Object( )
209 , m_nTicks( nTicks )
210 , m_nDeltaTime( -1 )
211{
212 //infoLog( "INIT" );
213}
214
215
216
218{
219 //infoLog( "DESTROY" );
220}
221
222QString SMFEvent::toQString() const {
223 return QString( getBuffer().toHex( ' ' ) );
224}
225
226
227// ::::::::::::::
228
229SMFNoteOnEvent::SMFNoteOnEvent( unsigned nTicks, int nChannel, int nPitch, int nVelocity )
230 : SMFEvent( nTicks )
231 , m_nChannel( nChannel )
232 , m_nPitch( nPitch )
233 , m_nVelocity( nVelocity )
234{
235 if ( nChannel >= 16 ) {
236 ERRORLOG( QString( "nChannel >= 16! nChannel=%1" ).arg( nChannel ) );
237 }
238}
239
240
241
243{
244 SMFBuffer buf;
247 buf.writeByte( m_nPitch );
248 buf.writeByte( m_nVelocity );
249
250 return buf.getBuffer();
251}
252
253
254// :::::::::::
255
256
257SMFNoteOffEvent::SMFNoteOffEvent( unsigned nTicks, int nChannel, int nPitch, int nVelocity )
258 : SMFEvent( nTicks )
259 , m_nChannel( nChannel )
260 , m_nPitch( nPitch )
261 , m_nVelocity( nVelocity )
262{
263 if ( nChannel >= 16 ) {
264 ERRORLOG( QString( "nChannel >= 16! nChannel=%1" ).arg( nChannel ) );
265 }
266}
267
268
269
271{
272 SMFBuffer buf;
275 buf.writeByte( m_nPitch );
276 buf.writeByte( m_nVelocity );
277
278 return buf.getBuffer();
279}
280
281};
#define INFOLOG(x)
Definition Object.h:240
#define ERRORLOG(x)
Definition Object.h:242
virtual QByteArray getBuffer() const =0
QByteArray m_buffer
Definition SMFEvent.h:48
QByteArray getBuffer()
Definition SMFEvent.h:38
void writeVarLen(long nVal)
Definition SMFEvent.cpp:61
void writeString(const QString &sMsg)
Definition SMFEvent.cpp:53
void writeDWord(long nVal)
Definition SMFEvent.cpp:44
void writeWord(int nVal)
Definition SMFEvent.cpp:37
void writeByte(char nByte)
Definition SMFEvent.cpp:31
virtual QByteArray getBuffer() const override
Definition SMFEvent.cpp:146
SMFCopyRightNoticeMetaEvent(const QString &sAuthor, unsigned nDeltaTime)
Definition SMFEvent.cpp:137
virtual ~SMFEvent()
Definition SMFEvent.cpp:217
virtual QString toQString() const override
Definition SMFEvent.cpp:222
SMFEvent(unsigned nTicks)
Definition SMFEvent.cpp:207
virtual QByteArray getBuffer() const override
Definition SMFEvent.cpp:270
SMFNoteOffEvent(unsigned nTicks, int nChannel, int nPitch, int nVelocity)
Definition SMFEvent.cpp:257
virtual QByteArray getBuffer() const override
Definition SMFEvent.cpp:242
SMFNoteOnEvent(unsigned nTicks, int nChannel, int nPitch, int nVelocity)
Definition SMFEvent.cpp:229
virtual QByteArray getBuffer() const override
Definition SMFEvent.cpp:116
SMFSetTempoMetaEvent(float fBPM, unsigned nDeltaTime)
Definition SMFEvent.cpp:107
SMFTimeSignatureMetaEvent(unsigned nBeats, unsigned nNote, unsigned nMTPMC, unsigned nTSNP24, unsigned nTicks)
Definition SMFEvent.cpp:170
virtual QByteArray getBuffer() const override
Definition SMFEvent.cpp:184
SMFTrackNameMetaEvent(const QString &sTrackName, unsigned nDeltaTime)
Definition SMFEvent.cpp:85
virtual QByteArray getBuffer() const override
Definition SMFEvent.cpp:94
@ NOTE_ON
Definition SMFEvent.h:57
@ NOTE_OFF
Definition SMFEvent.h:56
@ TIME_SIGNATURE
Definition SMFEvent.h:73
@ SET_TEMPO
Definition SMFEvent.h:72
@ COPYRIGHT_NOTICE
Definition SMFEvent.h:65
@ TRACK_NAME
Definition SMFEvent.h:66