eraps2@aspvax.UUCP (09/11/87)
Well, thought I'd put my two cents in. Yes, there is a problem. No, it is NOT in the hardware. No it is NOT in the Amiga software. It comes from using the wrong tool to do the job. Namely, serial.device is NOT well suited to use as a MIDI interface. Older midi programs had this problem - I am told (I still use a //e for MIDI) that the newer software does not suffer from this. Nonetheless, I for one would prefer a more general (and easier [for the application programmers]) solution, since I suspect much tweaking went into getting the programs to work. I experienced the problem early on when I first hooked up a MIDI cable to the Amiga and wrote some code to drive it. Stated basically, the problem is that the serial device does not time stamp the incomming data, and since the Amiga multitasks, by the time the program gets the code, the time 'may' be wrong since another task 'may' have run in between. Note that by disabling other tasks the problem vanishes (but then you can't multitask with the program). The other problem is that the serial device outputs the data as soon as it gets it - which may not be when the program sent it, thus messing up the outgoing timing. The same semi-solution applies. To get real-time preformance in this type of enviorment, the solution as traditionally been to put the nasty timing stuff in the driver. BUT, we can't really expect the serial device to handle time stamping since that is not necessary for normal serial applications. ****** Warning - Long Winded Suggested Solution Ahead ****** The Solution: Make a new device: midi.device. Requirements: ------------- 1) Ability to grab EVERY byte as it comes in to at least 33000 baud (3300 bytes/sec). 2) Ability to know WHEN the byte came in (so we can calculate the durations between note on and note off, etc ...) 3) Ability to send out bytes at precise points in time (at least to a good enough resolution to fool the ear) Current Implementation method: ------------------------------ Below, see a diagram of typical current recording method (some methods are highly ingeneous to minimize the problems discussed, but this is the basic problem). Read a byte <----------------- ask timer.device for the time | record note and time ----------- The problem with this is that the time is NOT accurate since after the byte has been read by the serial device, the task doing this may be interrupted. Also, although the serial device can read ALL the bytes, the task may not (in the short run, due to other tasks), be able to keep up with the bytes coming in, so that if the byte came and was buffered up by the serial device, the task might not read it for another 2 seconds, and then, even if the time it got was accurate, there is still a 2 second error in the timing. These problems are CLEARLY audible. A Solution: ----------- We need to do the time-stamping in the driver (where interupts are impossible and we will be accurate to AT LEAST 1/3300 0.3 ms. This lets us record accurately. Output should be double buffered and under control of the driver as well. The sequence to use the system might go something like this: open midi.device (default everthing to MIDI parameters) while (record) read_midi_value, place in buffer clear time value on 1st MIDI code/time element to 0 to playback: write_midi(1st 1024 MIDI code/time data elements in buffer) while (playback) write_midi(next 1024 MIDI code/time data elements in buffer) write_midi(last partial data (< 1024)) data format: [MIDI code][time since last code was read] Driver Requirements: new global: miditime last_time; /* actual time of last code received */ open: same as current driver, but make all values default to those MIDI uses (as described in the RKM). Therefore, setparms won't be used input: when a byte is received, place it in the buffer (as is currently done). also add to the buffer the elapsed time since the last byte was received. this is why we need a new global (or at least a static). Thus, now each input value is represented by 2 values, the actual code and a time-stamp. output: output MUST be buffered, since the task feeding us with values may be interupted at any time (and the music would hang until it became active again). The simplest solution is to write the values in blocks. Then the driver may output them 1 at a time until the buffer is exhausted. The problem with this alone is that the task feeding us may not be active at the exact instant we (the driver) need more values. For this reason, I suggest double buffering. Thus, while 1 buffer is being output, the task feeding us has the length of the 1st buffer to write a second. When the second buffer is being output, the task has that long to write the 1st buffer. To prevent the task from overflowing our buffers (writing a buffer we are not done with), the writes can be forced to a syncronous mode (thus if the task trys to write a 3rd buffer [overwrite the 1st], the request will not return [will hang the task] until space is available). This also means we need a new (or modified status command, to see if a previous write completed). schedule flow: (driven by user requests) wiat for a write request to come in. buffer available ? no - convert request to syncronous (so continue when buffer is free) yes - continue repeat use flow: (sub-function of schedule flow) Is buffer N ready to be output? (N == 0 or 1) no - wait yes - continue output buffer N = !N; repeat output flow: (driven by data output rate) get next code/time stamp element wait time stamp amout of time do this by schedualing an interupt using a CIA timer (I think this is what the serial device uses it for now anyway - to regulate output baud rate). output the code if end-of-buffer, switch buffers repeat. loop: NEW command, tells driver to copy any incoming byte directly to the output (since the task can't do this in real time, any many MIDI programs have this feature, we might as well provide it). Questions/problems to solve. What form should the timer values take - If the TOD (time of day) clock is accurate enough (.3 ms resolution or better), this is the ideal solution, since the MIDI codes are 8 bit and the TOD clock is 24 bits (and can be read directly off of a chip register), 1 32 bit word (long) can represent each value. Is 32 bits a waste of space for this maybe? At .3 ms per bit, 8 bits only gives us 78 ms max delay time - clearly inadequate, and 16 bits gives us 20 seconds - good, but NOT good enough unless we want to add a special code that the driver will not send out (to allow LONGER) delays - also the receive part of the driver would have to padd with these. Not elegant. 24 bits gives us 85 hrs between events - plenty. Ok, so we need 32 bits to represent each code. Can we use the TOD register value to provide this? I don't know, I will have to find out the resolution of this clock (do you know what it is?) If it is not good enough, we will have to generate a synthetic time value based on the 8 bit serial timer and the TOD (not tough, but not as clean). ============================================= Well, that's it ... anybody have something to do the trick? This is #3 on my hit list, so don't hold your breath waiting from my version. - Rob Ginn eraps1@nadc.arpa ...burdvax!jtids!aspvax!eraps2 "We want information ... information" Rob Ginn - No. 2 ...burdvax!jtids!aspvax!eraps2 eraps1@nadc.arpa
peter@sugar.UUCP (09/14/87)
I'm not a musician... these suggestions are purely from a software design standpoint and exposure to MIDI people (wow, what's that 5-pin jack in your neck for? :->). In article <15740@aspvax.UUCP>, eraps2@aspvax.UUCP writes: > [MIDI.DEVICE] > > 1) Ability to grab EVERY byte as it comes in to at least 33000 baud > (3300 bytes/sec). > 2) Ability to know WHEN the byte came in (so we can calculate the > durations between note on and note off, etc ...) I would suggest softening this requirement to know when the first byte of any MIDI packet comes in. This would require that the midi.device operate in terms of midi packets, but that's a good idea anyway. > 3) Ability to send out bytes at precise points in time (at least to > a good enough resolution to fool the ear) Again, make this "Ability to send out MIDI packets at precise points in time". > open midi.device (default everthing to MIDI parameters) In the open, specify what MIDI device number you want to be in the device field, that way you can have a number of midi programs running simultaneously without interfering with each other. You also want to echo midi messages from one program to all the other programs (sounds like SoundScape, don't it?). > while (record) > read_midi_value, place in buffer Read midi packets... > clear time value on 1st MIDI code/time element to 0 > to playback: > write_midi(1st 1024 MIDI code/time data elements in buffer) Write midi packets... > while (playback) > write_midi(next 1024 MIDI code/time data elements in buffer) > write_midi(last partial data (< 1024)) > > data format: > [MIDI code][time since last code was read] [MIDI packet][wallclock time packet arrived] > Driver Requirements: > new global: miditime last_time; /* actual time of last code received */ > > open: > same as current driver, but make all values default to those MIDI uses > (as described in the RKM). Therefore, setparms won't be used Use "unit number" in open to specify MIDI device number. > input: > when a byte is received, place it in the buffer (as is currently done). > also add to the buffer the elapsed time since the last byte was received. > this is why we need a new global (or at least a static). Thus, now each > input value is represented by 2 values, the actual code and a time-stamp. Whan a byte is received, buffer it up. When a MIDI packet is recieved, place it in the buffer or send it to the task, depending on the settings of timeout and buffer size. If a packet is interrupted by a higher priority packet (I don't remember whet these are called... system exclusive?), stack the first packet and accumulate (and pass on) the new one first. Then when it finishes unstack and finish gathering the old one. When the first byte of a MIDI packet is received, timestamp the packet. > output: > output MUST be buffered, since the task feeding us with values may be > interupted at any time (and the music would hang until it became active > again). The simplest solution is to write the values in blocks. Then > the driver may output them 1 at a time until the buffer is exhausted. The > problem with this alone is that the task feeding us may not be active at the > exact instant we (the driver) need more values. For this reason, I > suggest double buffering. Thus, while 1 buffer is being output, the task > feeding us has the length of the 1st buffer to write a second. When the > second buffer is being output, the task has that long to write the 1st > buffer. To prevent the task from overflowing our buffers (writing > a buffer we are not done with), the writes can be forced to a syncronous > mode (thus if the task trys to write a 3rd buffer [overwrite the 1st], the > request will not return [will hang the task] until space is available). This > also means we need a new (or modified status command, to see if a previous > write completed). It would be preferable to queue the packets being written up. That way, the task can be writing packets until the buffer fills (make it, like, 2K long). This would give you all the advantages of your method, but a lot more versatility. > schedule flow: (driven by user requests) > wiat for a write request to come in. room in the buffer? no - go to sleep until there is. yes - put the request in the buffer. Signal something to send. > repeat > > output flow: (driven by data output rate) wait for transmitter ready. anything to send? no - go to sleep until there is. yes - get next packet. if the packet has a non-zero timestamp wait until packet timestamp >= wallclock time. output the packet. signal room in the buffer. repeat > > loop: > NEW command, tells driver to copy any incoming byte directly to the > output (since the task can't do this in real time, any many MIDI > programs have this feature, we might as well provide it). It could do this for any device numbers that don't match open units in the midi.device as well. > Questions/problems to solve. > What form should the timer values take [... is 32 bits too big?] Not if you timestamp MIDI packets instead of bytes. You really only care about the time the first byte got in anyway. -- -- Peter da Silva `-_-' ...!hoptoad!academ!uhnix1!sugar!peter -- 'U` ^^^^^^^^^^^^^^ Not seismo!soma (blush)
ronhill@pnet01.CTS.COM (Ronald Hill) (09/16/87)
Does the Midi Device floating around the boards handle all of the problems you mentioned? UUCP: {cbosgd, hplabs!hp-sdd, sdcsvax, nosc}!crash!pnet01!ronhill ARPA: crash!pnet01!ronhill@nosc.mil INET: ronhill@pnet01.CTS.COM
jwabik@shamash.cdc.com (Jeff Wabik) (12/30/88)
Forgive me if this topic has come up recently... With the traffic here
these days, I haven't been able to keep up with it all and still keep
my sanity, and (what's left of my) sanity won out.. Anyhow ..
One of the toys I got for Christmas was a nice Casio (musical) keyboard,
with 7 billion sounds and nice ports on the back marked "MIDI IN", and
"MIDI OUT". I know what MIDI is and what its supposed to do, but I know
nothing about MIDI specifics on the Amiga.. Specificially:
1) What types of interface boxes are out there, what are the
differences, and which is best. Are there interfaces that
attach to the Amiga by other than the Serial port? Are
those 5-pin DIN looking cables as innocent (pin 1 to pin
1,...,pin 5 to pin 5) as they look?
2) What software is cool? I've heard Deluxe Music Construction
Set is funky. I saw the MIDI software flow thru .binaries.
last week, but haven't played yet .. I'd like to be able
to "program" a complicated score (like 4 voices, or more)
from the (musical) keyboard, then play back on either Amy
or the Casio ..
3) Why invented liquid soap and why?
Basically, I know nothing about this stuff so any other information
would be great, too..
Thanks!
-Jeff
--
Jeff A. Wabik INTERNET: jwabik@shamash.cdc.com AT&T: +1 612 853 6811
____ ____ UUCP: jwabik@shamash.UUCP FAX: +1 612 853 4789
/ ___||___ \
| |___ ___| | Control Data Corporation - We're not a computer company ..
\____||____/ but we play one on TV ..
"I want something with reclining leather seats that goes
really fast, and gets really shitty gas mileage .. "
mrr@amanpt1.zone1.com (Mark Rinfret) (01/05/89)
In article <10294@shamash.cdc.com>, jwabik@shamash.cdc.com (Jeff Wabik) writes: > Forgive me if this topic has come up recently... > > 1) What types of interface boxes are out there, what are the > differences, and which is best. Are there interfaces that There is a wide range of products available, ranging in price from $40-$100. The primary differences appear to be the number of MIDI ports available (In, Out, Thru, Sync, etc.). > attach to the Amiga by other than the Serial port? Are Nope. > those 5-pin DIN looking cables as innocent (pin 1 to pin > 1,...,pin 5 to pin 5) as they look? Yup. > > 2) What software is cool? I've heard Deluxe Music Construction > Set is funky. I saw the MIDI software flow thru .binaries. DMCS is a nice scoring package, but its MIDI user interface stinks. I can provide details if you want. DMCS is the only scoring package I use since I haven't seen anything better. Open question to other net.readers: Are there any good _configurable_ patch editors out there? I have a Casio CZ-1 (superset of the the CZ-101, CZ-1000, CZ-3000 family) which is not supported in any commercially available software. If I can buy a truly configurable patch editor (editable sysex codes, etc.) I won't have to finish writing mine :-). > last week, but haven't played yet .. I'd like to be able > to "program" a complicated score (like 4 voices, or more) > from the (musical) keyboard, then play back on either Amy > or the Casio .. Forget DMCS on this one. I'm not aware of a good alternative, though. As I understand it, you can record "tracks" of information with several of the sequencer products available (see below), but none of them provide a scoring interface. > > 3) Why invented liquid soap and why? Don't you mean "Why invented soap and who?" :-) :-). (I'm sure glad this wasn't Pete Da Silva's message. HIS typos are his OWN damned business! :-) ) > Basically, I know nothing about this stuff so any other information > would be great, too.. I haven't ventured into the "sequencer" area yet. Sequencers let you take "tracks" of pre-recorded MIDI information and edit it, cutting and pasting song segments much as you would edit a text document. I think you'd have to devote just about all of your free time to MIDI music in order to benefit from this level of effort. Get yourself some back issues of AmigaWorld and Amazing Computing. There are ads, product reviews, etc. for lots of this stuff. MIDI on the Amiga is great fun for me. Keep us posted on your progress. E-mail me if you want to chat some more. > > Thanks! > > -Jeff Sure! Mark -- < Mark R. Rinfret, mrr@amanpt1.ZONE1.COM | ...rayssd!galaxia!amanpt1!mrr > < HyperView Systems Corp. Home: 401-846-7639 > < 28 Jacome Way Work: 401-849-9390 x301 > < Middletown, RI 02840 Hypermedia R Us! >
scotty@ziggy.UUCP (Scott Drysdale) (01/07/89)
In article <540@amanpt1.zone1.com> mrr@amanpt1.zone1.com (Mark Rinfret) writes: >In article <10294@shamash.cdc.com>, jwabik@shamash.cdc.com (Jeff Wabik) writes: >> 2) What software is cool? I've heard Deluxe Music Construction >> Set is funky. I saw the MIDI software flow thru .binaries. > >DMCS is a nice scoring package, but its MIDI user interface stinks. I can >provide details if you want. DMCS is the only scoring package I use since >I haven't seen anything better. DMCS does have a few bugs, most of which can be worked around. all is not lost - read on. > >Open question to other net.readers: >Are there any good _configurable_ patch editors out there? I have a Casio >CZ-1 (superset of the the CZ-101, CZ-1000, CZ-3000 family) which is not >supported in any commercially available software. If I can buy a truly >configurable patch editor (editable sysex codes, etc.) I won't have to >finish writing mine :-). > >> last week, but haven't played yet .. I'd like to be able >> to "program" a complicated score (like 4 voices, or more) >> from the (musical) keyboard, then play back on either Amy >> or the Casio .. > >Forget DMCS on this one. I'm not aware of a good alternative, though. >As I understand it, you can record "tracks" of information with several >of the sequencer products available (see below), but none of them provide >a scoring interface. try the DMCS-SoundScape combination. soundscape is a "midi studio" type program which allows you to route various midi sources around to destinations and perform lots of operations on the midi stream. with DMCS and soundscape present in the system, DMCS will start up soundscape and appear as a midi source in the soundscape patch panel. from there, you can have dmcs play your score into soundscape's midi recorder and then edit the midi data and add events DMCS can't. you can also use a utility which comes with soundscape to convert recorded midi data to DMCS scores, with control over quantization of midi event duration to note length. of course, some stuff is lost in the translation, but it's probably easier than trying to write things down while fooling around at the keyboard. soundscape also allows you to write your own source/destination modules in C and will install them in the patch panel so they can be used like any other soundscape source/dest. this is useful for doing things like reserving a section of your keyboard for switching patches in a synth by converting the reserved keys to different midi events. i wrote a module which allows the keyboard to be split at as many arbitrary places as you like and allows the split regions to be sent to one or more different midi channels. soundscape is relatively easy to use (i got it recording/playing back without reading the manual). it will work with just about any midi interface for the amiga that plugs into the serial port (i built one out of about $15 worth of common parts). it seems to be pretty much bug free, too. check it out. --Scotty