[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference 7.286::atarist

Title:Atari ST, TT, & Falcon
Notice:Please read note 1.0 and its replies before posting!
Moderator:FUNYET::ANDERSON
Created:Mon Apr 04 1988
Last Modified:Tue May 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:1433
Total number of notes:10312

497.0. "RECORDING/PLAYING MIDI data" by ICHIN::MISKINIS () Thu Jun 01 1989 20:25

    Hello out there,
    
    	Has anyone had any experience with recording and playing
    back MIDI data?
    
    	I thought my code was working, but I tried it with a
    sound that doesn't decay, and I now realize that I'm missing
    note-off(s) or something...
    
    	I am willing to post a stand-alone program that will
    record/play data, HERE, WITH SOURCE code, if that will
    help get assistance...
    	
    	I'm interupting 4000 times a second, at which time I update
    several counters.  I split a quarter note (beat) into 24 pulses,
    each of which will contain a certain number of ticks (1/4000 sec)
    based on the tempo.  (120 BPM caused 128 ticks/per pulse, etc.)
    
    	ANYWAY, every 1/24 of a beat I see if there's MIDI data waiting
    to be read.  If so, I read it, and place it in an array, along with
    the beat and pulse that it was read.
    
    	The playback routine uses the same interupt routine, and checks
    to see if the beat and pulse of the next array element has come
    up.  If has, I write the MIDI data out.
    
    	The code runs fine, except that some notes stay on.  I was using
    a PIANO sound to test my code.  This sound would decay after a while
    thus leading me to believe that the notes were being turned off
    correctly...
    
    	ANY and ALL help/advise/comments/criticisms are appreciated...
    
    _John_
T.RTitleUserPersonal
Name
DateLines
497.1This may be pulling at strawsCIM16::POWERSI Dream Of Wires - G. NumanFri Jun 02 1989 12:5213
    RE: < Note 497.0 by ICHIN::MISKINIS >
                        -< RECORDING/PLAYING MIDI data >-

>    	I thought my code was working, but I tried it with a
>    sound that doesn't decay, and I now realize that I'm missing
>    note-off(s) or something...
    
        Some synths, instead of sending note off messages send note on
     messages with a velocity of 0.  I believe, this is allowed for in
     the midi 1.0 spec.  ( I hope I have that right )

     Bill Powers
497.2STILL Stumped!ICHIN::MISKINISMon Jun 05 1989 13:5025
    Hi Bill,
    
    	YES, you are correct...  There's also a RUNNING STATUS that
    I discovered, by which you can turn many notes on by sending
    NOTE_ON data1 data2 data1 data2 data1 data2....etc
    
    BUT!  Since I merely record EVERYTHING being sent by my synth,
    and PLAY IT BACK INTACT, I'm confused as to why notes will
    stay on...
    
    I've added a routine which analyzes the data, but haven't finished
    it yet.  I count all bytes I READ, and all bytes I WRITE, and they
    match up OK.  I even check to make sure the NOTE_ONs = NOTE_OFFs
    and in some cases when they are equal (RUNNING STATUS not used)
    some notes will STILL STAY ON!
    
    I'M STUMPED!  Anyway, I'm going to add a STEP TIME PROGRAMMING
    routine, in which case I will force a note_off for every note_on
    I send.  If this type of data causes notes to hang, then I know
    I'm missing some MIDI programming philosophy somewhere...
    
    AGAIN, ANY AND ALL HELP IS APPRECIATED!
    
    _John_
    
497.3a few paths to try...MUNCSS::BURKEMon Jun 05 1989 18:3318
    Since you seem to be in a desperate situation, I'll add some ideas,
    which you've probably already thought of:-
    
    1.	Try forcing a delay inbetween MIDI messages. If the problem
    	disappears, well...
    2.	Does your problem occur with all MIDI streams, or just some ?  What 
    	is the simplest (shortest) MIDI stream which displays the problem ?
    3.	Can the synth you are using definitely handle this data ?  (check it's 
    	MIDI spec). I know that my CZ-300 & TR505 can receive stuff which
    	they cannot transmit - maybe your machine can transmit stuff which
    	it can't read. 
    	Can you get a loan of another synth ?
    
    Hope it's of some use...
    Jim Burke
    
    PS	All the best with your sequencer project - you've taken on quite a 
    	task !
497.4MIDI recorder and player - mi and moREGENT::LOMICKARoy LomickaTue Jun 13 1989 18:1718
When the MT-240 hit this notes file a couple of months ago, I went out 
and bought one.  I'm not much of a musician, but all this MIDI stuff intrigued 
me and I decided to write a simple MIDI recorder and player that stores the 
MIDI events in a simple ASCII file format.  I call the recorder "mi" for 
MIDI input" and the player is "mo" which stands for for "MIDI output".  The 
programs are written in Mark Williams C and seem to work well with my MT-240 
and the Mark Williams shell, msh.

"mi" writes to "stdout", so from the shell, you type "mi >songfile.mi". 
"mo" reads from "stdin", so to play back, you use "mo <songfile.mi". 

To merely playback a performance without recording, you can "mi|mo". 

In the notes which follow, you will find the source code for mi and mo.  

I would appreciate it if one of you "real" musicians would record a live 
performance using mi and post the resulting file here.  I'd like to see 
if the mi mo system really works.
497.5mi.cREGENT::LOMICKARoy LomickaTue Jun 13 1989 18:1853
/* mi.c - records Atari ST midi input - writes to stdout - just start 
   typing your next shell command to terminate - output format is space-
   separated fixed width fields of ascii characters and consists of a
   time interval in 5 millisecond clock ticks (right justified in space-
   filled 10 column decimal integer field) followed by midi input bytes
   (2 hexadecimal digits each) followed by a newline - resolution is 5 ms
   (200 hz system clock) - time measurements can be inacurate if other CPU
   activity is occurring such as screen scrolling or disk output - time
   measurement error is local - cumulative time is as accurate as the 
   Atari clock - Roy Lomicka - 4/15/89
*/

/* future options
	-a omit time stamps (typically used when 
	   MIDI instrument sends clock pulses)
	-b ignore (do not record) MIDI clock pulses
*/

#include <osbind.h>
#include <bios.h>
#include <stdio.h>

#define hz_200 (unsigned long *)0x4BA
#define EXIT_SUCCESS 0
main( )
{
  unsigned long ch, tnew, told, dt, first;
  while( Bconstat( BC_MID)!=0) Bconin( BC_MID); /* flush out the buffer */
  first=1; /* flag for starting the clock */
  printf( "\n"); fflush(stdout);/* open the output stream */
  while( 1)
  { /* forever wait for midi or kbd input */
    while( !Bconstat( BC_MID)) /* wait for a byte */
    { /* no midi input - kbd input? */
      if( Bconstat( BC_CON)) exit( EXIT_SUCCESS);
    }
    /* OK, we've got midi input */
    { /* get and output the number of milliseconds 
	 since the last time we were here */
      tnew=peekl( hz_200);
      /* handle first time and clock wrap-around */
      if (first) {dt=0;first=0;} else {dt=tnew<told?tnew-(long)told:tnew-told;}
      told=tnew; printf( "%10ld", dt);
    }
    do
    { /* read and output all that's in the buffer (127 byte buffer in TOS) */
      ch=Bconin( BC_MID)&255L; printf( " %02lx", ch);
    } 
    while( Bconstat( BC_MID));
    printf( "\n"); fflush( stdout);
    /* note that longest possible line is somewhat under 512 bytes */
  }
}
497.6mo.cREGENT::LOMICKARoy LomickaTue Jun 13 1989 18:1955
/* mo.c - plays Atari ST midi output - reads from stdin - terminates 
   upon encountering end of file on stdin - input format is time 
   interval in 5 millisecond clock ticks followed by hexadecimal
   representation of midi input bytes to be transmitted in "one
   fell swoop" followed by newline - Roy Lomicka - 4/13/89
*/

#include <osbind.h>
#include <bios.h>
#include <stdio.h>

#define hz_200 (unsigned long *)0x4BA
#define EXIT_SUCCESS 0

char inbuf[512];
unsigned char hexval1[256]; /* values for high nybble */
unsigned char hexval2[256]; /* values for low nybble */

hexvalinit()
{
  int i;
  for (i=0;i<=63;i++) 
  {hexval1[i]=i*16&0xF0; hexval2[i]=i&0x0F;}
  for (i=64;i<=127;i++) 
  {hexval1[i]=(i+9)*16&0xF0; hexval2[i]=(i+9)&0x0F;}
  for (i=128+0;i<=128+63;i++) 
  {hexval1[i]=i*16&0xF0; hexval2[i]=i&0x0F;}
  for (i=128+64;i<=128+127;i++) 
  {hexval1[i]=(i+9)*16&0xF0; hexval2[i]=(i+9)&0x0F;}
  /* for (i=0;i<=255;i++) 
     printf("%3d %02x %02x\n", i, hexval1[i], hexval2[i]); exit(0); */
}

main( )
{
  unsigned long tinit, tnow, ttarg, dt; char midibyte;
  hexvalinit();
  tnow=0; tinit=peekl(hz_200);
  while (!feof(stdin))
  if (scanf("%10ld", &dt)==1)
  {
    /* printf("%10ld", dt); */
    ttarg=tnow+dt;
    /* wait until target time occurs */
    while (ttarg>(tnow=(peekl(hz_200)-tinit)));
    while (getchar()==' ') 
    {
      while (!Bcostat(BC_MID));
      midibyte=hexval2[getchar()]+hexval1[getchar()];
      Bconout( BC_MID, midibyte);
      /* printf(" %02x", midibyte); */
    }
    /* printf("\n"); */
  }
}
497.7But.. I have no MWCTALK::HARRIMANCuisine VeriteTue Jun 13 1989 19:057

	Could you possibly generate an executable and make it available?
	I can download but I haven't programmed the ST (if I had time,
	I'd try it, but I do a lot of MIDI programming instead)...

	/pjh
497.8mi1 and mo1 - standalone executable versions of mi and moREGENT::LOMICKARoy LomickaWed Jun 14 1989 13:1735
OK, here's a new version of mi and mo that is available in executable form. 

I call this version mi1 and mo1.

To make the programs executable from the desktop, they now accept a file 
name argument and no longer respond to redirection of stdin or stdout.

Here's the location:  REGENT::USER$C:[LOMICKA.PUBLIC.ST]MI1MO1.ARC 

Here's the .txt file that's in the arc file: 

Programs by Roy Lomicka 6/15/89

mi1 - Atari ST MIDI recorder

usage: from shell, mi1 songfilename
       from desktop open mi1.ttp and enter songfilename 

Caution - mi1 will overwrite without warning any existing
file having the same name as that specified in songfilename.

mo1 - Atari ST MIDI player

usage: from shell, mo1 songfilename
       from desktop open mo1.ttp and enter songfilename 

Caution - These programs will NOT work correctly if the
song file being read or written is on the FLOPPY disk.
Use your hard disk, if you have one, or for best results,
use a RAM disk.

Caution - Occasionally mi1 records a really out-of-range 
delta-t.  This will make mo1 appear to hang.  Maybe I blew 
the timer wrap-around handling.  If you fix this problem, 
please notify me.  REGENT::LOMICKA