Modulate serial data for transmission over audio channel - Page 1
Forum section: electronics / projects

author: stefan_o
author_rank: Regular Contributor
timestamp: February 27, 2022, 09:49:58 pm
content: Hello,for easy synchronous live recording of a MIDI out parallel to the audio signals, my idea is to record the MIDI data on an unused audio channel using some modulation, to later demodulate and save as MIDI on a PC.MIDI is just serial data at 31500 Baud/s (3150 Byte/s). This is less than what a 56k modem could do, and even considering not so great cables and a crappy audio ADC, you'll have a lot more bandwidth than on an analog telephone line (at least 60dB SNR / 15 kHz bandwidth).I tried looking for some kind of modem chip that contains the modulator and the DAC, but all I can find are all-integrated chips that require bi-directional communication or ones that are way to slow.Does anyone know if a) that kind of chip exists and is still obtainable at a reasonable price or b) there is some µC implementation that can do the modulation and output the signal using a DAC?Best regardsStefan

author: MasterT
author_rank: Frequent Contributor
timestamp: February 27, 2022, 10:12:24 pm
content: FYI, analog telecom lines 300 Hz - 3.4 kHz only. 56k modem had compression algorithm AFAIK, to "squize" data rate along 3.4k limits.uCPU implementation is just inverse (i)FFT.

author: Benta
author_rank: Super Contributor
timestamp: February 27, 2022, 10:14:31 pm
content: The bandwidth of your analog line is unclear, you seem to imply 15 kHz, please be more specific.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: February 28, 2022, 12:45:10 am
content: The trick is, 56k used multiple levels to get more bits per symbol; bandwidth just gives the rate limit, while dynamic range (bits/symbol) is given by noise floor. Digital bandwidth is the product of both. And indeed, typical POTS circuits are digitized over 64kbps channels with different kinds of encoding, so getting 56k into that, with completely different encoding methods (plus everything else that can happen), is not bad at all. Not that it would almost ever negotiate full speed, hehe.I forget what kind of modulation that was, raw levels, QAM, or what. It's... not something you'd want to do yourself. Not without being experienced in the subject, that is. I suppose, maybe GNU Radio comes with a stock option or something? Not sure what the best way is to get MIDI into that; can you pipe it in from a real MIDI interface on the machine? If nothing else it could be fed in as audio, which would need a different front end to recover correct bit levels and framing. Maybe that's another off-the-shelf configuration too...Anyways, this would be doable enough in a PC via application like that, and could go as simple as an introductory-level ARM MCU, more or less (given a more compact/optimized C program, of course). But I have no clue if you can find such a codec handy. Looks like there are some applications for streaming audio in/out via serial, but at just a little too low rate for what you're looking for. For what looks like exactly the problem you'd expect, the sample rate or frequency response isn't adequate to just dump raw serial into it.Tim

author: T3sl4co1l
author_rank: Super Contributor
timestamp: February 28, 2022, 01:18:23 am
content: Quote from: evb149 on February 28, 2022, 12:55:29 amSomehow I doubt just any instrument is going to be fast enough to do that directly; but as synth goes, that's a good way of expressing it -- just digital radio slowed down a bit so your ears can hear it!Tim

author: NiHaoMike
author_rank: Super Contributor
timestamp: February 28, 2022, 03:44:43 am
content: If you do it on a byte per byte level, at 48kHz, you'll have 15 samples (and a small dead period) to encode the byte into. One easy encoding would be to break up the byte into two 4 bit nybbles, then map them to 16 different levels. Out of the 15 samples you have, the first 4 would be two very positive followed by two very negative samples (something like 3/4 of full scale, so that clipping doesn't spoil the levels) for synchronization and as a reference amplitude. Then you have a zero sample as a guard interval followed by two positive samples of the first level (such that the maximum level would be large to get robustness against noise and two negative samples of the first level. After that would be two positive samples of the second level, two negative samples of the second level, and a zero sample as another guard interval.Note that because every positive sample has a matching negative sample, DC balance is guaranteed. There's also the tendency to duplicate samples so that it won't be running right at the bandwidth limit of the equipment (assuming it's 48kHz, 96kHz would make it easier!). On the receive side, signal quality can be improved by applying equalization to cancel out ISI caused by antialiasing filters.

author: jonpaul
author_rank: Super Contributor
timestamp: February 28, 2022, 01:35:29 pm
content: Bonjour à tous !If the OP encodes audio, (rather than MIDI music instruments commands) , a few points please!In 1980s, AES Standard Commission and European Broadcast Union Promulgation of AES/EBU, standards for serial transmission of digital audio.FULL DISCLOSURE.... I was on that committee, to write and maintain the standard as well as AES-42 std. for digital microphones.AES/EBU and AES3 is a balanced 110 Ohm line, RS485 PHY interfaces, transformers,https://www.wikiaudio.org/aes-ebu/https://en.m.wikipedia.org/wiki/RS-485Data format is an embedded clock 128 xFS and data,16 bit stéréo via Manchester Code, FS 32..48 kHz with data phase encoded on the clock.Later révisions had 24 bit data and FS 28 kHz to 384 kHz.Subsequent Broadcast equipment manufacturers demanded a 75 Ohm unbalanced, PHY, thus AES3id, for unbalanced coax,use.Since 1986, the mixed Signal IC firms subsequently designed and manufactured dedicated TX, RX, transceivers and SRC Sample Rate Converters, TI, ADI, AKM, Cirrus Logic. Belden, Mogami, and other cable manufacturers supply specific cables for this standard.I hope that this note answers all your questions.Bon Soirée,Jon

author: AaronD
author_rank: Frequent Contributor
timestamp: February 28, 2022, 03:45:59 pm
content: This is interesting.Once upon a time (shortly out of college), I wrote a MIDI<->WAV file conversion app that essentially simulated a UART driving an oscilloscope, with the output going directly to a mono WAV file with no further massaging. I believe I used full-scale DC to directly represent the two logic levels, and sampled at 96kHz to give me a reasonably close baud rate with integer division. (3 samples per bit: 96kHz/3 = 32kbaud, which is 2.4% fast) The app would also recover a functional MIDI file from this "captured UART": the time signature and tempo were lost, so I used SMPTE frames instead, but the stream of commands when played was identical.The idea was to use a DAW to synchronize it to a soundtrack, and then play the resulting multitrack file with the DAC for the MIDI channel going to a MIDI receiver, for eventual use in a MIDI-driven musical light show. The caveat, of course, is that both the DAW and the player (if separate) must NEVER modify the MIDI track!(I think I also had an analog comparator with an adjustable negative threshold, to account for an AC-coupled audio path settling close to zero for a long idle period)I never went all the way through with it, but at least the conversion app worked. I built the receiver too, with the comparator driving an MCU's UART, but I abandoned the project before I tested it. Of course, there are better ways to do all of this, but I didn't know that then...(I suspect that the data integrity might have been lower than expected because even 96kHz audio and higher is often lowpassed just a hair above 20kHz, with a high-order digital filter in the converter, in both directions.)

author: Benta
author_rank: Super Contributor
timestamp: February 28, 2022, 08:14:08 pm
content: Quote from: Benta on February 27, 2022, 10:14:31 pmMy original question is still open.But if you have 15 kHz bandwidth, 4-QPSK or 4-QAM should be enough for the purpose. Pretty easy to implement.

author: stefan_o
author_rank: Regular Contributor
timestamp: February 28, 2022, 09:07:37 pm
content: Thanks for all those replies. To illustrate the use case: During a live gig using a digital mixer a multichannel recording of all audio inputs is very easy nowadays. But MIDI recording is almost never implemented, which would be grate to have later during mixing the recording (maybe you want to add/change the instrument or the effects the keyboard had during the live gig).Of course there are midi recorders, but that's another device you have to start/stop, you'll have to sync it later etc. So my idea is somekind of MIDI-di-box, you plug MIDI in and you'll get modulated MIDI audio out on XLR, that you can record and later demodulate to a midi file.My hopes where to have some simple µC like an AVR that reads the MIDI data, passes the data using I²C or SPI to an modulator chip and have some output circuity to create a balanced output signal at the correct level. But as nobody suggested a modulator chip I assume it doesn't exists.A PC for modulation is not an option, for practical application it should be a device that you plug in and it just works. I want it work reliable at 16 Bits/44.1 kHz digital recording (although in practice it's most likely 24 Bits/48 kHz). To avoid troubles with low-cut/high-cut filters or noise from ground loops it shouldn't start below 120 Hz and not exceed 16 kHz. Ideally there would also be some kind of error correction used to ensure data integrity over short drop-outs (like some bad fridge starting up causing audio interference).Unfortunately I don't know much about about modulation or programming for DSP, so 4-QPSK or 4-QAM is not easy for me to implement.I know there is DRM ("Digital Radio Mondiale") which transmits digital audio over AM (16-QAM or 64-QAM), and could just reach the required bitrate at 10 kHz bandwidth. But unfortunately it seems to be almost always SDR, the approch of many projects I could find is very similar to my idea: Use an soundcard to record the still modulated signal from the receiver and demodulate/decode in software. This is fine for demodulation, I could use GNU Radio there, but not for modulation, for that I need simple hardware.

author: Benta
author_rank: Super Contributor
timestamp: February 28, 2022, 09:25:25 pm
content: Quote from: stefan_o on February 28, 2022, 09:07:37 pmFirst it was 15 kHz, now it's 10 kHz. Are you kidding us?Is your hobby wasting people's time?

author: nctnico
author_rank: Super Contributor
timestamp: February 28, 2022, 09:34:41 pm
content: Quote from: stefan_o on February 28, 2022, 09:07:37 pmA reasonable ARM microcontroller running at 50MHz should be able to do it. IQ modulation / demodulation is not that hard to achieve in software but you'll need to add bit stuffing encoding schemes to make sure the resulting signal has a constant amplitude so you can use an AGC algorithm AND the receiver can synchronise to the bitstream. Error correction algorithms are also available.@Benta: the 10kHz comes from a reference to an entirely different application namely transmitting data over the air; more or less indicating that 10kHz should be enough bandwidth for the required bitrate.

author: stefan_o
author_rank: Regular Contributor
timestamp: February 28, 2022, 11:34:34 pm
content: Quote from: Benta on February 28, 2022, 09:25:25 pmI was giving an example of an existing system (DRM) that uses 10 kHz bandwidth. Correct me if I'm wrong, but having 15 kHz bandwidth available means a system that only uses 10 kHz could be used (as long as it meets the required bitrate)? As I wrote a few sentences before, the range from 120 Hz to 16 kHz is available (which I rounded down to 15 kHz).Quote from: nctnico on February 28, 2022, 09:34:41 pmAs long as there isn't a project somewhere that I could adapt I don't see a chance for me to do that reasonable time.There was an idea to split a byte into two nibbles and use 16 different levels for each nibble. I probably would also have to send a reference level and I'm not sure 16 different levels can be safely demodulated when they are just short pulses. But that gave me an idea: Is it possible to modulate each byte as an audio signal on a PC, and then just use a look-up table in the µC to "play" each byte? As MIDI messages are at maximum 3 bytes maybe a 4th byte could be send with error correction information. If I increase the upper frequency limit to 17.3 kHz (using a samplerate of 34666 Hz) there would be 8 samples per Byte. Is a reasonable pre-calculated modulation possible with that (without introducing any DC)?The timing is also important: It is not possible to group for example 16 byte in one buffer to send it as one block, as the time when they have been received is important and should be the same as the time a byte is send as the audio data.

author: nctnico
author_rank: Super Contributor
timestamp: February 28, 2022, 11:50:38 pm
content: An option is to look for modem chips that support QAM modulation; that would be some kind of off-the-shelve solution to do the modulation & demodulation part.Didn't check suitability for your project but these look interesting to research:https://www.maximintegrated.com/en/products/comms/73M2901CE.htmlhttps://www.directindustry.com/prod/cml-microcircuits/product-34037-782131.htmlBe aware though that these are kind of boutique parts so use with care if you intend to make a mass product out of it.

author: AaronD
author_rank: Frequent Contributor
timestamp: March 01, 2022, 01:35:39 am
content: Quote from: stefan_o on February 28, 2022, 11:34:34 pmSysex (System Exclusive) messages have undefined length, and are terminated instead with a reserved byte value. They're often used to dump patches (audio samples) and other configuration, control media gear (play/pause, lighting, pyrotechnics, etc.), or whatever someone decides to stick into a MIDI stream.Once you jump through the protocol hoops to say that "this is a sysex intended for this device", it almost becomes a general-purpose 7-bit UART with everything else ignoring it until the reserved termination character. (the 8th bit is reserved for protocol control characters, of which the terminator is one)

author: stefan_o
author_rank: Regular Contributor
timestamp: March 01, 2022, 03:04:32 am
content: Quote from: AaronD on March 01, 2022, 01:35:39 amFortunately I could detect that and always generate and send the error correction as the last byte covering the 3 bytes before (sysex messages are not the normal use case, but of course shouldn't be a problem, so reduced error correction is acceptable.Quote from: nctnico on February 28, 2022, 11:50:38 pmThe first part seems way to slow (I've seen several of those), the second one could be suitable, but full datasheet requires registration and couldn't find any place that sells this part, I assume it's a special part with a very special price. Also it requires packets of 15 Bytes minimum and looking at the generated overhead it needs way to much bandwidth.I just had a look at QAM modulation and at least modulation seems to be very easy (to do it, I have not looked at the theory why it works): All you do is I(t)*cos(f*t) + Q(t)*sin(f*t), for digital applications you define for each symbol a fixed value for I and Q (Gray code is the preferred way to assign), for 16 QAM you have two different levels for I and Q (negative and positive), so a total of 16 different pairs of I/Q. To have sin and cos you need at least 4 samples, so it would be possible to use 8 samples for one byte using 16 QAM? 256 QAM could transmit an complete byte with 4 samples. Is it more useful to use 256 QAM and have 8 points for the DAC (and reduce bandwidth) or send the sample twice? If it's really that simple I'll write some test code to create audio files, that I'll playback/record. I assume proper demodulation is a lot harder.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: March 01, 2022, 05:09:22 am
content: For point of reference -- it sounds interesting enough, and feels like something I could do for example; though I'm not familiar with MIDI in depth, and haven't written a whole-ass RF modulator of this complexity before, so there's some uncertainty there. So if I were quoting it, I'd want to high-ball more like 200 hours maybe, and that would probably cover firmware design and a basic platform (the circuit board is the easiest part, or just using off-the-shelf dev boards even). Also, my availability isn't great at the moment, so, you can probably find someone better experienced (faster?) if you're serious about this.Anyway, that (times typical labor rates) sets a ballpark budget for product development, and then the question is -- so, obviously this is something you'll find useful, but is it just a one-off sort of thing, or, how many do you think you could sell as a product proper? And are you even interested in pursuing that (sales and marketing), or would you prefer this just be an item that you (and anyone else) can get? In any case, what kind of investment proposition is there, maybe you can find enough buyers to distribute that cost?My feeling is -- it certainly sounds useful, and it's simple enough that, surely it's been thought of before; so, the fact that it doesn't seem to exist, suggests it's just not very worthwhile. Maybe synchronizing MIDI isn't such a pain after all, it's a poor substitute sure, but it works?Or maybe it's not as simple as you envision; I can see, well -- if you've loaded all the recorded channels into the editing station right, and you're playing it back piece by piece -- but MIDI is stateful, you can't just jump into the middle of a command, or even a sequence of commands necessarily (or maybe you can, again, I'm no expert!), so the decoder at the very least needs to keep track of what's going on in the grander scheme of things, to also play back commands that are meaningful. So like, it'd have to be some whole-assed plugin for the editor/tracker, that converts things while you're editing. And it can't be careless, you can't delete a few milliseconds here or there in the encoded track, you'll corrupt the data -- probably it needs to be converted to MIDI on loading, or something, and so that can only be done in an editing tool that supports raw audio plus MIDI tracks simultaneously. So, maybe/probably that's fairly trivial in professional tools, but it's not something I think like Audacity can do for example.So, resolving all those issues -- depending on which ones, and how much they're actually a problem -- you're talking making some kind of whole-ass plugin and dealing with the editor's API, and probably some GUI elements, and that could drag on for months now. Then duplicate some of that effort, porting it to another editor, and so on, however many you wish to support. Put another way: it's not enough to have a dongle that does the claimed thing, but it also needs to convert back, and it needs to be usable (good user experience (UX)). So it's not clear just how in-depth a product like this could really be!Tim

author: AaronD
author_rank: Frequent Contributor
timestamp: March 01, 2022, 01:44:55 pm
content: Quote from: stefan_o on March 01, 2022, 03:04:32 amThere are also real-time messages that can appear at any time, even in the middle of other messages. So a Note On might originally be 90 3C 40 in hex, but what appears on the wire could be 90 F8 3C FC 40, with the F8 being a "sync pulse" and the FC a sequence-stop command, in the middle of a still-valid Note On.https://www.midi.org/specifications-old/item/table-1-summary-of-midi-messageIf I were doing this, I would probably give up trying to decode and error-correct the protocol proper, and just blindly encode each byte as it's received. Maybe some byte-level error-correction, but not protocol-level. If I get a bad stream in, then it appears on the recording as received, not corrected in that sense.

author: AaronD
author_rank: Frequent Contributor
timestamp: March 01, 2022, 01:54:08 pm
content: You might also have a look at the "Data Signal Modulator" (DSM) peripheral that some PIC's have. It's essentially a 2:1 MUX between two digital waveforms (clocks, PWM, DC, etc.), with the bitstream or other signal (UART, comparator, etc.) as the selection input. Plus an option to synchronize (delay) the switch according to one or the other waveform, or both or neither. All of the connections can be external as well, in case you can't generate the right signal internally, or if you already have the right signal as an input anyway.Don't know if that helps you or not, but it seems tantalizingly close even if not.

author: stefan_o
author_rank: Regular Contributor
timestamp: March 02, 2022, 12:49:37 am
content: On the synchronization issue: As MIDI is UART (it's just a serial port like RS232 with other levels (in fact current) and another connector) there is no clock at the input, a byte can arrive at any time, all I have to ensure is that my output is always faster than the input. Of course there will be a delay between the received byte and the output byte, but that should be constant and can be compensated during demodulation (no intention for real-time transmission, demodulation is offline).Of course I will test my code on a PC first before I start working on a µC (whenever possible I'll do that). I wrote a proof-of-concept QAM-modulator that uses a look-up table and modulate any kind of input file into an 32 kHz unsigned 8-bit mono wave audio file (usage: qammod 16/256 inputfile outputfile.wav). This could be implemented even in an ATTiny. I have no idea if the signal it's generating is even close to correct.I tried to make the signal visible in GNU Radio using a "GUI Constellation Sink", but a complex signal is required, but either a) I cannot figure out how to correctly do that or b) the modulation doesn't work. It doesn't show random dots, rather two rotating lines composed of 4 groups of 2 dots each.

author: nctnico
author_rank: Super Contributor
timestamp: March 02, 2022, 12:56:21 am
content: You'll need to output two WAV files. One for the Q and one for the I signal. Alternatively you can add a demodulator to your GNU radio signal chain.

author: stefan_o
author_rank: Regular Contributor
timestamp: March 02, 2022, 01:05:02 am
content: Quote from: nctnico on March 02, 2022, 12:56:21 amBut I will not have a complex signal, I read in the GNU Radio "IQ Complex Tutorial" that the idea of I/Q is to avoid the high sampling rates, so a 1 GHz signal can be sampled at 1 GHz and doesn't require 2 GHz. But this what I have: 16 kHz bandwidth sampled at 32 kHz. How do I convert a real signal to a complex one at half the sampling rate?

author: ebclr
author_rank: Super Contributor
timestamp: March 02, 2022, 09:14:08 am
content: Welcome to 21 centuryhttps://github.com/gdsports/midi-wifi-demos

author: gf
author_rank: Super Contributor
timestamp: March 02, 2022, 09:45:20 am
content: Quote from: stefan_o on March 02, 2022, 01:05:02 am1) Down-mix the sampled real signal with a complex 8kHz LO (-> quadrature mixer), or in other words, multiply the signal with exp(-j*2*PI*8000*t). This shitfs the whole spectrum down by 8kHz, hereby moving the 0...16kHz band to -8...8kHz. More precisely, since we are dealing with discretely sampled data, the spectrum is finite and and wraps around circularly, therefore the shift actually becomes a rotate, which has the side effect that the -16kHz...-8kHz band does not move down to -24..-16kHz (which were outside the -fs/2..fs/2 spectrum range), but it moves to 8..16kHz. Note, after multiplication with the complex LO, the formerly real signal is now complex.2) Then apply an ideal boxcar lowpass filter with a cut-off at 8kHz, which eliminates frequencies > 8kHz and < -8kHza)3) Finially down-sample by a factor of 2 (if you really want to reduce the sample rate as well, but this is optional).Since an ideal boxcar lowpass won't be realizable, you need to renounce some banwidth in practice, for the filter's transition band, (for instance by utilizing only 1..15kHz instead of 0..16kHz).EDIT: Note that exp(-j*2*PI*8000*t) = cos(2*PI*8000*t) - j*sin(2*PI*8000*t)EDIT:a)Note that the frequencies > 8kHz and < -8kHz, which are eliminated here, are eventually the down-converted negative frequencies of the original real signal.EDIT: Adding visualization, possibly easier to understand than text.Spectrum components of the sampled real baseband signal:-16 -8 0 8 16+---------+---------+---------+---------+| mirr(B) | mirr(A) | A | B |+---------+---------+---------+---------+After quadrature down-mixing in the digital domain:-16 -8 0 8 16+---------+---------+---------+---------+| mirr(A) | A | B | mirr(B) |+---------+---------+---------+---------+After lowpass:-16 -8 0 8 16+---------+---------+---------+---------+| | A | B | |+---------+---------+---------+---------+where mirr(x) stands for the conjugate complex of a left <-> right mirror of x

author: stefan_o
author_rank: Regular Contributor
timestamp: March 02, 2022, 04:13:46 pm
content: Quote from: ebclr on March 02, 2022, 09:14:08 amI have no idea how this is even remotely related to my use caseI tried to demodulate with multiplying to LO and lowpass filtering in GNU Radio, no success, after low pass dots are completely random in the constellation viewer. I also read that QAM requires transmitter and receiver to have a common phase reference, which is not the case here. A common way is to have burst signals (color burst in composite video signal), but that's not possible here, as the bytes are not synchronized to a reference clock I would send a burst every time, only once at startup is also not possible, as the µC and the the clock of the ADC will drift.Back to the idea of splitting the bytes into nibbles and coding them with 16 different levels. What if instead of using 16 constant values using a frequency with 16 different levels? It seems this is called ASK and shouldn't require any phase information? Is there an easy way to demodulate that?

author: gf
author_rank: Super Contributor
timestamp: March 03, 2022, 01:03:29 pm
content: Quote from: stefan_o on March 02, 2022, 04:13:46 pmFor a bit rate of 32kbit/s and 16 levels (4 bits per symbol), you need a symbol rate of 8k symbols/s.Your available bandwidth is +/-8kHz, below and above an 8kHz carrier (lower and upper side bands).The main lobe of an ASK spectrum with 8k symbols per second basically fits into this bandwidth, but the side lobes need to be discarded (-> pulse shaping).But I'm not sure if you can easily hit the "eyes" on the receiver side if you use 16 levels.With 4 amplitude levels it looks much more relaxed, but then 32kbit/s do not fit into your available bandwidth.At a lower symbol rate, 16 levels may be more relaxed too, but again, 32kbit/s do not fit into your available bandwidth then.Code:% generate stream of random symbols% 8k symbols/s, 320kSa/s, 40 samples/symbolnumlevels = 16x = randi([0 numlevels-1], 1, 800);x = repmat(x,40,1)(:)';x -= mean(x);% limit bandwidth to +/-8KHzX = fft(x); % 10Hz/binX(801:end-800) = 0;x = real(ifft(X));% plot eye diagramy = reshape(x,80,length(x)/80)';clf; for i = 1:399; plot(y(i,:)); hold on; end; grid on

author: AaronD
author_rank: Frequent Contributor
timestamp: March 03, 2022, 01:59:07 pm
content: Quote from: gf on March 03, 2022, 01:03:29 pmTaking things to a bit of an extreme, what if we assume a 16-bit audio input at 44.1kHz (practical minimum on paper for pro audio recording, probably better in practice, minus analog noise), and feed it 3125 symbols/sec with 256 possible levels per symbol? My thought is that the receiver has more than enough bits (on paper) to distinguish all of those symbols, and the 14 supposed-to-be-identical samples per symbol allows some error correction at the far end.(or instead of being identical, they might be shaped in some way to reduce the required bandwidth to preserve that shape, but the concept is the same; just a bit more math)

author: gf
author_rank: Super Contributor
timestamp: March 03, 2022, 02:48:50 pm
content: It is eventually the shaping in conjunction with a large number of levels, which "ruins" the eye diagram.If you had enough bandwidth to transmit square pulses, then you'd get fully open eyes, even with a large number of levels.And even 20kHz audio is only 25% more than the previously assumed 16kHz -- butseveral times higherwere nice to make things easier.Stefan_o is looking for an easy/trivial way. But modems with a high spectral efficiency are not that simple, at the end, even if the basic principle is not so complicated. The devil is in the details (carrier phase recovery, symbol synchronization, channel estimation and equalization, etc.)

author: T3sl4co1l
author_rank: Super Contributor
timestamp: March 03, 2022, 03:02:14 pm
content: The trouble is if those symbols get smeared out into each other (ISI, due to nonlinear phase response), or the gain is wrong. Sending min/max level symbols every so often could serve as AGC reference, maybe say DC restore, and perhaps clock recovery as well (maybe in complementary 0/255 pairs or something). Some of which can be solved with still more levels and clever coding schemes, error correction, etc. Introducing still more overhead to the channel, but what do you expect.Tim

author: stefan_o
author_rank: Regular Contributor
timestamp: March 03, 2022, 03:19:39 pm
content: I'm looking for an easy solution, if I could use an off-the-shelf-chip that does a super complex modulation and there is demodulation code available I'm more than happy to use it (that was my original intention, unfortunately these chips doesn't seem to exist). I looked into those simple wireless communication chips (like from TI), but they are all super-integrated, even if they meet bandwidth and bitrate criteria (which is very difficult to tell from the datasheets), they all directly output RF, not a signal for an external tuner.Something like an 28.8k V34 modem chip with an external clock, that can run at twice the speed for increased datarate/bandwidth.There seem to be a lot of devils hidden in the details when doing the modulation in software and I don't know much about that. Unless I find a suitable chip or a project that I can adapt for my purpose I don't think I can achieve a reliable working result with reasonable time/effort.

author: gf
author_rank: Super Contributor
timestamp: March 03, 2022, 07:27:53 pm
content: Did you already take a look at spandsp?It's a soft-modem implementation supporting various modem protocols, FAX, AT command set,...V.29 @9600bits/s might cover your needs, if you manage to run it at 4-fold speed / sample rate.I don't know any details about the internals, though.https://github.com/freeswitch/spandsphttps://www.soft-switch.org/spandsp-modules.htmlhttps://www.soft-switch.org/

author: stefan_o
author_rank: Regular Contributor
timestamp: March 03, 2022, 09:43:28 pm
content: That's an interesting idea. spandsp is a rather big library with lots of functionality, but it only supports V.29. I assume I have to insert some timing data as there probably larger packets than just one byte each, so more bitrate is required. But I looked for a V34 soft-modem and found this:https://github.com/geofft/linmodemIt's implementation seems to be rather independent, so I can just take a few source files without the need for a huge library. And there seems to be some test code that modulates and then demodulates data, which is pretty much what I need. The only downside: It uses floating-point math, so I'll probably have to use an µC with an FPU (I'm not sure if it's only used during initialization to generate tables or all the time, in the first case soft-float is probably ok, in the second I'm not sure). It's quite old, but it was written by Fabrice Bellard, who later started ffmpeg and QEMU, so I have quite high hopes.

author: nctnico
author_rank: Super Contributor
timestamp: March 03, 2022, 10:30:30 pm
content: Quote from: T3sl4co1l on March 03, 2022, 03:02:14 pmYou'll need to make sure to have clock recovery but also make sure that the signal has a near perfect AC level. Simply translating groups of bits to levels is not going to cut it. 8b/10b encoding is often used:https://en.wikipedia.org/wiki/8b/10b_encoding

author: LordXaos
author_rank: Contributor
timestamp: March 04, 2022, 06:39:41 am
content: Just a few ideas that sprang to my mind while reading the thread: a Hamming code for forward error correction would be rather easy to do on even a very lowly µC and would map each MIDI byte to 12 bits. This might not be the ideal solution in terms of bits per error corrected, but it is rather simple to compute, so why not.Other than that: Data rate appears to be (as probably already stated) 3125 MIDI bytes per second (as they are sent as 10 bits at the bit rate of 31250 from what Wikipedia says), so it might be possible to use a continuous signal half that frequency (about 1.5kHz) as a reference clock, and then use multiples of that frequency as additional bands to modulate data on, like 4 bits each on 3KHz, 4.5kHz and 6kHz maybe, encoding 4 bits each as 16 different levels. If the DAC is synchronized to a proper multiple of the base frequency (say about 24kHz) then the signal could be stored as a table of just 16 entries, and the symbol frequencies can be derived from that table by changing step size, with the final output sample produced by conditional additions and bit shifts only.Having that constant reference sine wave at relatively high level should make any dynamics processors (gates, compressors) in the mixing console pretty much cease what they are doing to the signal, 16 levels are few enough that they might be distinguished using some windowed FFT (especially since the windows can be synchronized to the data signal by means of the reference signal), and any EQ could probably be fought by having the additional bands normally on and subtracting the modulated signal, so the EQ could be recovered (I don't know your FOH engineers, but I would protect against that) and cancelled at the target.This might have some kinks, but is at least rather simple to implement and should probably run on an Arduino for the encoding portion. Decoding is perhaps trickier, but there you should have all the time in the world and computing resources without end.Just my 2 cents.

author: stefan_o
author_rank: Regular Contributor
timestamp: March 04, 2022, 12:59:23 pm
content: Quote from: LordXaos on March 04, 2022, 06:39:41 amI had similar ideas, but level changes are causing more than just an intensity change of that frequency. I tried by using a single 8kHz signal and 16 different levels, the FFT shows noise everywhere, sou you would have to change intensity very slow, but then you don't get the bitrate.

author: AaronD
author_rank: Frequent Contributor
timestamp: March 04, 2022, 01:21:27 pm
content: Another idea:Generate a distinctive audio signal as a sort of absolute time reference (or tap off of an already-distinctive audio signal from the band), and run that to a custom MIDI recorder that you create entirely. Or generate the audio sync *from* the MIDI recorder and feed it to the audio recorder instead of the encoded MIDI data. (since you were going to have that connection anyway)Your MIDI recorder might produce a stereo WAV file (or FLAC if you have the oomph to encode it in real-time), but the MIDI channel of that comes directly from the UART and is never analog at all, nor is it processed by who-knows-what like LordXaos mentioned. A custom PC app could then take the multitrack audio recording and this "stereo" MIDI recording, sync them up over the entire length (clock drift...), extract the MIDI data (which would be the trivial part now), and then tie the useful stuff together.

author: gf
author_rank: Super Contributor
timestamp: March 05, 2022, 09:31:22 am
content: Quote from: stefan_o on March 04, 2022, 12:59:23 pmOne way to achieve a long symbol duration (or in other words, a low symbol rate) w/o renouncing bitrate is to distribute the bits to be transmitted among a large number of carriers. Making the carriers orthogonal wrt. the detection interval furthermore avoids interference between the carriers within a symbol. Well, that leads us to OFDM then. In fact, an ordinary OFDM modulation via IFFT + cycic prefix (CP) insertion is not difficult, and demodulation via FFT is not complicated either. The tricky part is again the symbol timing recovery at the rceiver (i.e. locate the position of the symbols in the received stream of samples). However, if the OFDM carriers are only ASK modulated, then phase does not matter, and due to the guard interval filled with the CP, the symbol timing does not need to be exact either, but you have some tolerances. But the receiver's FFT window should not cross symbol boundaries in the received stream of samples. One carrier (or a few ones) can be used as pilot, acting as amplitude reference, and possibly also for symbol timing synchronization.QuoteYes, well spotted. I should have been aware of linmodem, too, but it wasn't in my mind anymore.

author: AaronD
author_rank: Frequent Contributor
timestamp: March 06, 2022, 05:56:32 pm
content: Quote from: stefan_o on March 03, 2022, 09:43:28 pmI don't know either, about needing real-time floating-point math, but even if it does, could you get away with rewriting it to use fixed-point math instead? Essentially, the idea is to use a different unit than 1, and count those units instead. For example, you might count by 1/16ths, and thus have 4 fractional bits in what the hardware thinks is an integer, at the expense of 4 bits worth of headroom.I've seen a general-purpose 32-bit fixed-point library that was pre-optimized to use 16.16 throughout, which is 16 fractional bits while the hardware thinks it's using 32-bit integers.And a DSP library that uses 4.28, which is 28 fractional bits in a 32-bit "integer", with full-scale to the outside world represented as +/- [1.0 - 1 lsb] in that format. (+/- 0x0FFFFFFF) (this gives you 4 bits above and 4 bits below a standard 24-bit converter, for what that's worth, and the middle 24 bits correspond exactly to what the converters give and want to get)Of course, the mismatch between the software and hardware understandings means that you have to "unshift" or "preshift" things explicitly when ("integer") multiplying or dividing, to keep the fractional point where you want it (might be done better on some chips, with a union of partially overlapping structs: write one and read the other, for that much of a shift all at once), but these libraries took care of that for you.If you wrote your own, then you'd need to think about that too, or at least keep track yourself of where the fractional point has gotten to at each point in the code. (maybe you can afford to accumulate some and correct all at once later, or maybe the result is okay with or even needs a different location from what the input has and so you leave it there, etc.)Anyway, would something like that do what you need? It would certainly be faster than soft-float!

author: nctnico
author_rank: Super Contributor
timestamp: March 06, 2022, 10:02:13 pm
content: Quote from: AaronD on March 06, 2022, 05:56:32 pmThat is only a problem if it is a problem. Better do tests with the code as it is and then see if it is to slow or not. And if it is too slow, concentrate on the parts that consume most of the cycles first. Starting by rewriting code to make it faster without a clear objective is a foolish waste of time.