I am working on a MIDI effect (a VST plugin which modifies incoming MIDI generates new data and forwards it out) using the Juce Framework in C++. I see that it's technically possible to generate a new MIDI message with EVERY sample making my stream of MIDI flow at 16 to 24 bits 41,000 times a second or more. This seems entirely impossible for MIDI hardware to handle.
Is there any guideline or rule I must adhere to when when I decide on my bandwidth for MIDI over USB to hardware synths, new and old?
EDIT:
I should add that for what I am trying to do, higher bandwidth would help, but should work with hardware such as the Arturia Minibrute. I am attempting to do novel things like apply envelopes and LFOs to the modulation and pitch wheel.
MIDI over DIN cables runs at 31250 bits/s, i.e., 3125 bytes/s.
The USB MIDI specification does not specifiy any bandwidth, but the underlying USB bulk transfer protocol implicitly allows the receiving device to decide when to accept new packets.
In other words, the USB MIDI device can decide how fast it runs, but there is no easy mechanism to determine this limit (especially if your OS just drops MIDI messages that the device driver cannot deliver fast enough).
USB/MIDI interfaces run at exactly 3125 bytes/s.
USB MIDI devices where no 'real' MIDI interface is involved might be able to run faster; for example, my SC-8820 can process about 10 KB/s.
In practice, you cannot know what hardware sits behind some generic MIDI port.
You should use the 3125 bytes/s limit unless you have special knowledge about the device.
Related
I have a controller design application where i get data from 3 USB devices (seen as virtual com port under windows), process it, and then send the action to a 4th USB device (also virtual com port). I need to process that data once i recieve it with a minimum latency.
I decided to use C++ on windows embedded and do the serial communication using the .Net System::IO::Ports and DataReceived event. I tested my code performance using only one USB device where USB device sends one byte to the computer and then the computer sends it back. I measure the time difference and it was totally indeterministic. Sometimes 2 ms and sometime 20 ms.
Note: the process priority is set to be realtime.
Is it a better way to get a deterministic latency where a max delay is guaranteed? may be another API suitable for realtime serial communication on windows embedded?
Thanks in advance
In Windows, you cannot get a deterministic latency delay. You cannot have any guarantee. Because it is not a real-time OS.
If you want some guarantee that are mandatory for your project, you can either deport the real-time part into a smaller device like Arduino (open-source, some users made a Real Time OS with it) or a Beck chip (commercial, delivered with a Real Time miniOS); or you can install a RealTime Linux, which brings in some guaranteed delay.
I have an AHRS (attitude heading reference system) that interfaces with my C++ application. I receive a 50Hz stream of messages via Ethernet from the AHRS, and as part of this message, I get UTC time. My system will also have NTPD running as the time server for our embedded network. The AHRS also has a 1PPS output that indicates the second roll-over time for UTC. I would like to synchronize the NTPD time with the UTC. After some research, I have found that there are techniques that utilize a serial port as input for the 1PPS. From what I can find, these techniques use GPSD to read the 1PPS and communicate with NTPD to synchronize the system time. However, GPSD is expecting a NMEA formatted message from a GPS. I don't have that.
The way I see it now, I have a couple of optional approaches:
Don't use GPSD. Write a program that reads the 1PPS and the Ethernet
message contain UTC, and then somehow communicates this information
to NTPD.
Use GPSD. Write a program that repackages the Ethernet message into
something that can be sent to GPSD, and let it handle the
interaction with NTPD.
Something else?
Any suggestions would be very much appreciated.
EDIT:
I apologize for this poorly constructed question.
My solution to this problem is as follows:
1 - interface 1PPS to RS232 port, which as it turns out is a standard approach that is handled by GPSD.
2 - write a custom C++ application to read the Ethernet messages containing UTC, and from that build an NMEA message containing the UTC.
3 - feed the NMEA message to GPSD, which in turn interfaces with NTPD to synchronize the GPS/1PPS information with system time.
I dont know why you would want drive a PPS device with a signal that is delivered via ethernet frames. Moreover PPS does not work the way you seem to think it does. There is no timecode in a PPS signal so you cant sync the time to the PPS signal. The PPS signal is simply used to inform the computer of how long a second is.
there are examples that show how a PPS signal can be read in using a serial port, e.g. by attaching it to an interrupt capable pin - that might be RingIndicator (RI) or something else with comparable features. the problem i am seeing there is that any sort of code-driven service of an interrupt has its latencys and jitter. this is defined by your system design (and if you are doing it, by your own system tailored special interrupt handler routine - on a PC even good old ISA bus introduced NMI handlers might see such effects).
to my best understanding people that are doing time sync on a "computer" are using a true hardware timer-counter (with e.g. 64 bits) and a latch that gets triggered to sample and hold the value of the timer on every incoming 1PPS pulse. - folks are doing that already with PTP over the ethernet with the small variation that a special edge of the incoming data is used as the trigger and by this sender and receiver can be synchronized using further program logic that grabs the resulting value from the built in PTP-hardware-latch.
see here: https://en.wikipedia.org/wiki/Precision_Time_Protocol
along with e.g. 802.1AS: http://www.ieee802.org/1/pages/802.1as.html
described wikipedia in section "Related initiatives" as:
"IEEE 802.1AS-2011 is part of the IEEE Audio Video Bridging (AVB) group of standards, further extended by the IEEE 802.1 Time-Sensitive Networking (TSN) Task Group. It specifies a profile for use of IEEE 1588-2008 for time synchronization over a virtual bridged local area network (as defined by IEEE 802.1Q). In particular, 802.1AS defines how IEEE 802.3 (Ethernet), IEEE 802.11 (Wi-Fi), and MoCA can all be parts of the same PTP timing domain."
some article (in German): https://www.elektronikpraxis.vogel.de/ethernet-fuer-multimediadienste-im-automobil-a-157124/index4.html
and some presentation: http://www.ieee802.org/1/files/public/docs2008/as-kbstanton-8021AS-overview-for-dot11aa-1108.pdf
my rationale to your question is:
yes its possible. but it is a precision limited design due to the various internal things like latency and jitter of the interrupt handler you are forced to use. the achievable overall precision per pulse and in a long term run is hard to say but might be in the range of some 10 ms at startup with a single pulse to maybe/guessed 0,1 ms. - doing it means proving it. long term observations should help you unveiling the true practical caps with your very specific computer and selected software environment.
I'm writing a program in C++, on Windows. I need to support Windows Vista+.
I want to record both the microphone and speaker simultaneously.
I'm using the WASAPI and can record the microphone and speaker separately, but I would like to have just one stream supplying me the input from both streams (for example, for recording a client play the guitar along with the music he hears on his headphones), instead of merging the two buffers together somehow (which I guess will lead me to timing issues).
Is there a way to do this?
I'm actually working on a library which can do exactly that, merge streams from multiple devices. You might want to give it a try: see xt-audio.com. If you're implementing this yourself, here's some things to consider:
If you're capturing the speakers through a WASAPI loopback interface you're operating in shared mode, in this case latency might be unacceptable for live performance. If possible stick to exclusive mode and use a loopback cable or hardware loopback device if you have one (e.g. the old fashioned "stereo mix" devices etc).
If you're merging buffers then yes, you're going to have timing issues. This is generally unavoidable when syncing independent devices. Pops/clicks can largely be avoided using a secondary intermediate buffer which introduces additional latency, but eventually you're going to have to pad/drop some samples to keep streams in sync.
Do NOT use separate threads for each independent stream. This will increase context switches and thereby increase the minimum achievable latency. Instead, designate one device as the master device, wait for that device's event to be raised, then read input from all devices whether they are "ready" or not (this is were dropping/padding comes into play).
In general you can get really decent performance from WASAPI exclusive mode, even running multiple streams together. But for something as critical as live performance you might want to consider a pro audio interface with ASIO drivers where everything just ticks off the same clock, or synchronization is at least handled at the driver level.
I have to write a C++ application that reads from the serial port byte by byte. This is an important need as it is receiving messages over radio transmission using modbus and the end of transmission is defined by 3.5 character length duration so I MUST be able to get the message byte by byte. The current system utilises DOS to do this which uses hardware interrupts. We wish to transfer to use Linux as the OS for this software, but we lack expertise in this area. I have tried a number of things to do this - firstly using polling with non-blocking read, using select with very short timeout values, setting the size of the read buffer of the serial port to one byte, and even using a signal handler on SIGIO, but none of these things provide quite what I require. My boss informs me that the DOS application we currently run uses hardware interrupts to get notification when there is something available to read from the serial port and that the hardware is accessible directly. Is there any way that I can get this functionality from a user space Linux application? Could I do this if I wrote a custom driver (despite never having done this before and having close to zero knowledge of how the kernel works) ??. I have heard that Linux is a very popular OS for hardware control and embedded devices so I am guessing that this kind of thing must be possible to do somehow, but I have spent literally weeks on this so far and still have no concrete idea of how best to proceed.
I'm not quite sure how reading byte-by-byte helps you with fractional-character reception, unless it's that there is information encoded in the duration of intervals between characters, so you need to know the timing of when they are received.
At any rate, I do suspect you are going to need to make custom modifications to the serial port kernel driver; that's really not all that bad as a project goes, and you will learn a lot. You will probably also need to change the configuration of the UART "chip" (really just a tiny corner of some larger device) to make it interrupt after only a single byte (ie emulate a 16450) instead of when it's typically 16-byte (emulating at 16550) buffer is partway full. The code of the dos program might actually be a help there. An alternative if the baud rate is not too fast would be to poll the hardware in the kernel or a realtime extension (or if it is really really slow as it might be on an HF radio link, maybe even in userspace)
If I'm right about needing to know the timing of the character reception, another option would be offload the reception to a micro-controller with dual UARTS (or even better, one UART and one USB interface). You could then have the micro watch the serial stream, and output to the PC (either on the other serial port at a much faster baud rate, or on the USB) little packages of data that include one received character and a timestamp - or even have it decode the protocol for you. The nice thing about this is that it would get you operating system independence, and would work on legacy free machines (byte-by-byte access is probably going to fail with an off-the-shelf USB-serial dongle). You can probably even make it out of some cheap eval board, rather than having to manufacture any custom hardware.
I know that serial ports work by sending a single stream of bits in serial. I can write programs to send and receive data from that one pin.
However, there are a lot more other pins on the serial port connection that normal aren't used but from documentation all seem to have some sort of function for signalling as opposed to data transfer.
Is it possible in any way to cause the other pins that are not used for direct data transfer to be controlled individually? If so, how would i go about doing that?
EDIT: more information
I am working with a modern CPU running windows 7 64-bit on an intel core i7 870 processor. I'm using serial to usb ports because its imposable for me to do anything directly with a usb port and my computer does not come with serial ports and also for some inexplicable reason i have a bunch of these usb to serial port adapters lying around.
My goal is to control mutipul stepper motors (200 steps per rotation, 4 phase motors). My simple circuitry accepts single high pulses and interprets it as a command to cause the motor to rotate one step. The circuit itself will handle the power supply and phase switching. I wish to use the data transfer pin to send the rotation signals (we can control position and velocity by altering the number of high pulses and frequency of high pulses through the pin, however there is no real pulse width modulation).
I have many motors to control but they do not need to be controlled simultaneously. I hope to use the rest of the pins and run them through a simple combination logic circuit to identify which motor is being moved and which direction it is to move in. This is part of the power switching circuitry.
The data transfer pin will operate normally at some low end frequency. However, i want to control the other pins to allow me to give a solid on or off signal (they wont be flipping very quickly, only changes when i switch to controlling another motor).
Based of the suggestion of Hans Passant , I'd like to suggest that you use an Arduino instead of an USB-to-serial converter. The "Duemilanove" is an Arduino-based board that provides 6 PWM outputs (as well as 8 other digitial I/Os and 6 analog). Some more specialized boards might be even cheaper (Arduino Pro Mini, $15 in volume, some soldering required).
Using the handshaking pins to send data can work very well, though probably not on a multitasking OS, it's just very processor intensive (because the port needs to be polled constantly) and requires some custom cables. In fact, back in the day, this is exactly how Laplink got such high transfer rates over serial connections (and why to get those rates you needed a special 'Laplink' cable). And you need both sides of hte link to be aware of what's going on and be able to deal with the custom communications. Laplink would send a packet of data over both the normal UART pins while trying to send data from the other end of the packet over the handshaking pins. If the correct cable wasn't used (or there was some other problem with sending over the handshaking pins) there was no problem - all the data would just get send normally.
Embedded developers might know this as 'bit banging' - often on small embedded systems there's no dedicated UART circuitry - to get serial communications to work they have to toggle a general I/O pin with the correct timing. The same can be done on a UART's handshaking pins. But like I said, it can be detrimental to the system if other work needs to be done.
You can use DTR and RTS only, but that is four possible states. You do need to be careful that the device on the other end uses TTL levels. At he end of this link Serial there are tips on hardware if you need it.
What kind of data rate are you thinking of when you say high frequency? What kind of serial port do you have? With the old 9 pin connectors on the back of the computer the best you can do is around 115Kbps. With a USB adapter I have done test where I could push close to 1Mbps through the port.
Here's an article from Microsoft that goes into great detail on how to work with serial ports:
http://msdn.microsoft.com/en-us/library/ms810467.aspx
It mentions EscapeCommFunction for directly controlling the DTR line.
Before you check out this information, I'm joining in with the others that say a serial port is inappropriate for your application.
I´ve been trying to find an answer to your question for 3 hours, seems like there is no "simple way" to get a simple boolean signal from a computer...
But, there is always a way, and jet, as simple (maybe even stupid) as this may sound, have you considered using the audio jack connector as an output?, It is stereo so you would have 2 outputs available,the programming would is not that difficult. and you don#t need to buy expensive shit to make it work.
If you also need an input, just disassemble a mouse... and bridge the sensors to the servos, probably the most cheap and easiest way of doing it...
Another way would be using the leds for the Num-lock, caps-lock and the dspl-lock on the keyboard, these can be activated using software, and you just need to take a cheap external keyboard, and use the connectors for these 3 leds.
you are describing maybe a parallel port - where you can set bit patterns all at once - then toggle the xmit line to send it all...
Lets take a look from the "bottom up" point of view:
The serial port pins
Pins on the serial port may be connected to a "controller" or directly connected to the processor. In order for the processor to have access (control) the pins, there must be an electrical connection from the pins to the processor. If not, the processor nor the program can control the pins.
Using a serial controller
A controller, such as a USART, would be connected between the serial port and the processor. The controller may function as to convert 8 parallel data bits into serial bitstream. In the big picture, the controller must provide access to the port pins in order for them to be controlled. If it doesn't, the pins can't be accessed. The controller must be connected to the processor in order to control the pins if a controller is connected.
The Processor and the Serial port
Assuming that the pins you want to control are connected to the processor, the processor must be able to access them. Sometimes they are mapped as physical addresses (such as with an ARM processor), or they may be connected to a port (such as the intel 8086). A program would access the pins via a pointer or using a i/o instruction. In some processor, the i/o ports must be enabled and initialized before they can be used.
Support from the OS
Here's a big ticket item: If your platform has an Operating System, the Operating System must provide services to access the pins of the serial port. The services could be a driver or an API function call. If the OS doesn't provide services, you can't access the serial port pins.
Permission from the OS
Assuming the OS has support for the serial port, your program must now have permission to access the port. In some operating systems, permission may only be granted to root or drivers and not users. If your account does not have permission to access the pins, you are not going to read them.
Support from the Programming Language
Lastly, the programming language must have support for the port. If the language doesn't provide support for the port you may have to change languages, or even program in assembly.
Accessing the "unused" pins of a serial port require extensive research into the platform. Not all platforms have serial ports. Serial port access is platform dependent and may change across different platforms.
Ask another, more detailed question and you will get more detailed answers. Please provide the kind of platform and OS that you are using.