2 /*******************************************************************************/
3 /* Copyright (C) 2008 Jonathan Moore Liles */
5 /* This program is free software; you can redistribute it and/or modify it */
6 /* under the terms of the GNU General Public License as published by the */
7 /* Free Software Foundation; either version 2 of the License, or (at your */
8 /* option) any later version. */
10 /* This program is distributed in the hope that it will be useful, but WITHOUT */
11 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
12 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
15 /* You should have received a copy of the GNU General Public License along */
16 /* with This program; see the file COPYING. If not,write to the Free Software */
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /*******************************************************************************/
44 /* fill in the number of tracks */
45 if ( _num_tracks_pos )
47 fseek( _fp, _num_tracks_pos, SEEK_SET );
48 write_short( _tracks );
59 smf::open ( const char *name, int mode )
61 _name = strdup( name );
65 _fp = fopen( _name, mode == smf::WRITE ? "w" : "r" );
70 /*************************/
71 /* Private bit twiddlers */
72 /*************************/
75 smf::read_long ( void )
78 unsigned long ret = 0;
82 ret += *(buf + 0) << 24;
83 ret += *(buf + 1) << 16;
84 ret += *(buf + 2) << 8;
91 smf::read_short ( void )
94 unsigned short ret = 0;
98 ret += *(buf + 0) << 8;
105 smf::read_var ( void )
107 unsigned long ret = 0;
110 /* while bit #7 is set */
111 while ( ( ( c = read_byte() ) & 0x80 ) != 0x00 )
114 /* shift ret 7 bits */
128 smf::read_bytes ( void *p, int l )
130 fread( p, l, 1, _fp );
136 smf::read_byte ( void )
145 smf::write_var ( long var )
150 /* we shift it right 7, if there is
151 still set bits, encode into buffer
153 while ( ( var >>= 7) )
156 buffer |= ( var & 0x7F ) | 0x80;
161 write_byte( buffer );
172 smf::write_long ( unsigned long x )
176 buf[0] = ( x & 0xFF000000 ) >> 24;
177 buf[1] = ( x & 0x00FF0000 ) >> 16;
178 buf[2] = ( x & 0x0000FF00 ) >> 8;
179 buf[3] = x & 0x000000FF;
181 write_bytes( buf, 4 );
185 smf::write_ascii ( const char *buf )
187 if ( strlen( buf ) != 4 )
188 ASSERTION( "invalid MIDI value" );
190 write_bytes( (void *)buf, 4 );
194 smf::write_short ( unsigned short x )
198 buf[0] = (x & 0xFF00 ) >> 8;
201 write_bytes( buf, 2 );
205 smf::write_byte ( byte_t b )
207 write_bytes( &b, 1 );
212 smf::write_bytes ( const void *p, size_t l )
214 fwrite( p, l, 1, _fp );
220 /*************************/
221 /* Read and write tracks */
222 /*************************/
224 /* write event /e/ to the currently open file (should only be used in a track)
225 if /cue/ is true, transform a notes-on/off into cue messages */
227 smf::write_event ( const midievent *e )
229 tick_t ts = e->timestamp();
230 tick_t delta = ts - _time;
235 if ( _cue && (e->is_note_off() || e->is_note_on() ) )
237 /* begin cue message */
238 write_byte( 0xF0 ); /* sysex */
240 write_var( 7 ); /* length of this message */
242 static byte_t data[] = { 0x7F, /* MTC */
244 0x05 }; /* cue message */
246 write_bytes( data, sizeof( data ) );
248 write_byte( e->opcode() == event::NOTE_ON ? 0x05 : 0x06 );
249 write_short( e->note() );
264 if ( me.opcode() == event::NOTE_OFF )
266 me.opcode( event::NOTE_ON );
267 me.note_velocity( 0 );
272 /* write with running status */
273 if ( buf[0] != _status )
275 write_bytes( buf, l );
279 write_bytes( buf + 1, l - 1 );
285 smf::write_header ( int fmt )
287 write_ascii( "MThd" );
288 write_long( 6 ); /* Always 6 bytes of header */
292 write_short( fmt ); /* format, SMF-0 for 1 track SMF-2 for more */
294 _num_tracks_pos = ftell( _fp );
297 write_short( 0xDEAF );
302 /* start a new MIDI 'chunk', /id/ is 4 letters of ASCII */
304 smf::open_chunk ( const char *id )
307 ASSERTION( "chunks cannot be nested!" );
311 /* reset track length counter */
312 _length_pos = ftell( _fp );
314 write_long( 0xBEEFCAFE ); /* length, this has to be filled in at track end! */
321 smf::close_chunk ( void )
323 /* fill in track length */
324 long here = ftell( _fp );
326 fseek( _fp, _length_pos, SEEK_SET );
328 write_long( _tally );
330 fseek( _fp, here, SEEK_SET );
338 smf::open_track ( const char *name, int num )
340 open_chunk( "MTrk" );
342 if ( _format == 2 && num >= 0 )
343 write_meta_event ( smf::SEQUENCE, num );
346 write_meta_event ( smf::NAME, name );
352 // FIXME: write time signature here
356 smf::close_track ( tick_t length )
359 write_meta_event( smf::END, length ? length - _time : 0 );
367 smf::write_meta_event ( byte_t type, int n )
369 write_var( type == smf::END ? n : 0 ); /* delta time */
370 write_short( 0xFF00 + type );
372 /* write length bytes */
391 case smf::PROPRIETARY:
395 // FIXME: handle time sig, key sig, proprietary
402 smf::write_meta_event ( byte_t type, const char *s )
405 write_short( 0xFF00 + type );
411 case smf::INSTRUMENT:
426 ASSERTION( "event type does not take text!" );
431 /** write song gloabl info (only used on playlist track) */
433 smf::write_song_info ( int mode, int phrases, int patterns, const char *name, const char *notes )
435 write_meta_event( smf::PROPRIETARY, 5 + (4 * 2) /* length */ );
437 write_ascii( "Non!" );
440 write_long( phrases );
441 write_long( patterns );
444 write_meta_event( smf::NAME, name );
446 write_meta_event( smf::TEXT, ":: Created by the Non-Seqeuncer" );
449 write_meta_event( smf::TEXT, notes );
453 smf::write_phrase_info ( const phrase *p )
456 write_meta_event( smf::TEXT, p->notes() );
458 char *s = p->viewport.dump();
461 snprintf( pat, sizeof( pat ), "Non: xywh=%s",
466 write_meta_event( smf::PROPRIETARY, strlen( pat ) );
467 write_bytes( pat, strlen( pat ) );
470 /** write proprietary pattern info meta event */
472 smf::write_pattern_info ( const pattern *p )
474 write_meta_event( smf::PORT, p->port() );
478 snprintf( pat, sizeof( pat ), "%s: %s", p->mapping.type(), p->mapping.name() );
480 write_meta_event( smf::INSTRUMENT, pat );
483 write_meta_event( smf::TEXT, p->notes() );
485 char *s = p->viewport.dump();
487 snprintf( pat, sizeof( pat ), "Non: xywh=%s, ppqn=%d, key=%d, note=%d, mode=%d",
488 s, p->ppqn(), p->mapping.key(), p->note(), p->mode() );
492 write_meta_event( smf::PROPRIETARY, strlen( pat ) );
493 write_bytes( pat, strlen( pat ) );
496 /* turn on note->cue translation for this track */
509 smf::read_text ( void )
513 char *s = (char*) malloc( l + 1 );
524 smf::read_header ( void )
529 if ( strncmp( id, "MThd", 4 ) )
532 if ( read_long() != 6 )
535 _format = read_short();
536 _tracks = read_short();
537 _ppqn = read_short();
547 fseek( _fp, 14, SEEK_SET );
555 smf::skip ( size_t l )
557 fseek( _fp, l, SEEK_CUR );
562 smf::backup ( size_t l )
568 smf::read_track_name ( void )
574 for ( num = 0; ; ++num )
578 read_var(); /* delta */
579 status = read_byte();
581 /* stop at first non meta-event */
582 if ( status != midievent::META )
585 int opcode = read_byte();
598 backup( _pos - where );
603 /** read next Cue Point event on track */
605 smf::read_cue_point ( void )
607 read_var(); /* delta */
609 int status = read_byte();
611 if ( status != midievent::META )
614 int opcode = read_byte();
616 if ( opcode != smf::CUEPOINT )
623 smf::read_song_info ( int * mode, int * phrases, int *patterns, char **name, char **notes )
631 for ( num = 0; ; ++num )
635 read_var(); /* delta */
636 status = read_byte();
638 /* stop at first non meta-event */
639 if ( status != midievent::META )
642 int opcode = read_byte();
646 case smf::PROPRIETARY:
648 int len = read_var();
650 if ( len < 5 + (2 * 4) )
656 if ( strncmp( id, "Non!", 4 ) )
660 *phrases = read_long();
661 *patterns = read_long();
669 char *text = read_text();
671 if ( ! strncmp( text, "::", 2 ) )
690 backup( _pos - where );
698 smf::read_phrase_info ( phrase *p )
704 for ( num = 0; ; ++num )
708 read_var(); /* delta */
709 status = read_byte();
711 /* stop at first non meta-event */
712 if ( status != midievent::META )
715 int opcode = read_byte();
720 /* currently, this is ignored */
725 p->name( read_text() );
726 DMESSAGE( "Track name: %s", p->name() );
728 case smf::INSTRUMENT:
732 p->notes( read_text() );
734 case smf::PROPRIETARY:
738 char *data = (char *) alloca( l ) + 1;
740 read_bytes( data, l );
746 if ( 1 != sscanf( data, "Non: xywh=%a[0-9:]",
748 WARNING( "Invalid phrase info event" );
751 p->viewport.read( s );
757 /* Track ends before any non meta-events... */
763 WARNING( "skipping unrecognized meta event %02X", opcode );
768 backup( _pos - where );
772 return num ? p : NULL;
775 /** inform pattern /p/ from meta-events at the beginning of the
778 smf::read_pattern_info ( pattern *p )
784 bool name_set = false;
786 for ( num = 0; ; ++num )
790 read_var(); /* delta */
791 status = read_byte();
793 /* stop at first non meta-event */
794 if ( status != midievent::META )
797 int opcode = read_byte();
802 /* currently, this is ignored */
807 p->name( read_text() );
808 DMESSAGE( "Track name: %s", p->name() );
811 case smf::INSTRUMENT:
813 char *s = read_text();
817 if ( 1 == sscanf( s, "Instrument: %[^\n]", pat ) )
819 if ( ! p->mapping.open( Mapping::INSTRUMENT, pat ) )
821 p->mapping.open( Mapping::SCALE, "Chromatic" );
822 WARNING( "could not find instrument \"%s\"", pat );
826 if ( 1 == sscanf( s, "Scale: %[^\n]", pat ) )
828 if ( ! p->mapping.open( Mapping::SCALE, pat ) )
830 p->mapping.open( Mapping::SCALE, "Chromatic" );
831 WARNING( "could not find scale \"%s\"", pat );
838 p->port( read_byte() );
843 /* also accept TEXT event as name if no name was
844 provided--this is found in a number of older MIDI
846 p->name( read_text() );
850 p->notes( read_text() );
852 case smf::PROPRIETARY:
856 char *data = (char *) alloca( l ) + 1;
858 read_bytes( data, l );
862 int ppqn, key, note, mode;
865 if ( 5 != sscanf( data, "Non: xywh=%a[0-9:], ppqn=%d, key=%d, note=%d, mode=%d",
866 &s, &ppqn, &key, ¬e, &mode ) )
867 WARNING( "Invalid pattern info event" );
870 p->viewport.read( s );
876 p->mapping.key( key );
884 /* Track ends before any non meta-events... */
890 WARNING( "skipping unrecognized meta event %02X", opcode );
895 backup( _pos - where );
899 return num ? p : NULL;
903 smf::next_track ( void )
905 /* first, skip to the end of the track we're on, if any */
907 skip( _length - _pos );
909 while ( ! feof( _fp ) && _track < _tracks )
913 _length = read_long();
915 if ( strncmp( id, "MTrk", 4 ) )
917 WARNING( "skipping unrecognized chunk \"%s\"", id );
918 /* not a track chunk */
928 return _length = _pos = 0;
932 /** locate track number /n/ */
934 smf::seek_track ( int n )
941 for ( int i = 0; next_track(); ++i )
949 smf::track_listing ( void )
952 ASSERTION( "attempt to get track listing while in the middle of reading a track." );
954 char **sa = (char**)malloc( sizeof( char* ) * (_tracks + 1) );
957 long where = ftell( _fp );
959 for ( i = 0; next_track(); ++i )
961 sa[i] = read_track_name();
962 sa[i] = sa[i] ? sa[i] : strdup( "<Unnamed>" );
967 /* go back to where we started */
968 fseek( _fp, where, SEEK_SET );
974 /* print track list for file /name/ */
976 smf::print_track_listing ( const char *name )
980 f.open( name, smf::READ );
984 char **sa = f.track_listing();
987 for ( int i = 0; (s = sa[i]); ++i )
988 printf( "Track %3d: \"%s\"\n", i, s );
991 /** read all remaining events in current track and return them in a list */
993 smf::read_track_events ( tick_t *length )
995 list <midievent> *events = new list <midievent>;
1000 byte_t oldstatus = -1;
1005 while ( _pos < _length )
1011 int status = read_byte();
1013 if ( ! (status & 0x80) )
1022 tick = (time * PPQN) / _ppqn;
1024 e.timestamp( tick );
1026 int opcode = status & 0xF0;
1028 // e.status( opcode );
1033 case event::NOTE_OFF:
1034 case event::NOTE_ON:
1035 case event::AFTERTOUCH:
1036 case event::CONTROL_CHANGE:
1037 case event::PITCH_WHEEL:
1039 read_bytes( data, 2 );
1041 /* handle note off, vel 0 */
1042 if ( opcode == event::NOTE_ON && 0 == data[1] )
1044 e.opcode( event::NOTE_OFF );
1048 e.data( data[0], data[1] );
1050 events->push_back( e );
1052 /* TODO: set MIDI channel here */
1054 case event::PROGRAM_CHANGE:
1055 case event::CHANNEL_PRESSURE:
1057 data[0] = read_byte();
1061 events->push_back( e );
1064 /* TODO: hanlde proprietary events? */
1065 if ( midievent::META != status )
1067 if ( 0xF0 == status )
1069 /* looks like a sysex */
1073 ASSERTION( "unrecognized message" );
1075 byte_t *data = (byte_t *) alloca( 4 );
1077 read_bytes( data, 4 );
1081 if ( data[0] == 0x7F &&
1084 /* looks like a cue message! */
1090 e.status( event::NOTE_ON );
1091 e.note( read_short() );
1092 events->push_back( e );
1097 e.status( event::NOTE_OFF );
1098 e.note( read_short() );
1099 events->push_back( e );
1103 ASSERTION( "unrecognized cue message" );
1108 DMESSAGE( "converting MIDI cue to note-on/off n: %d", e.note() );
1115 WARNING( "unrecognized opcode %02X", status );
1121 opcode = read_byte();
1125 case smf::END: /* track end */
1126 /* track extends until this event */
1130 WARNING( "corrupt MIDI file in track end" );
1134 WARNING( "unhandled meta-event %02X", opcode );
1147 /**************************/
1148 /* accessors (for reader) */
1149 /**************************/
1152 smf::format ( void ) const
1158 smf::tracks ( void ) const