Open smarek opened 5 years ago
I saw your commit associated with retdec.
It’s not the same sort of tool, but Ghidra can also be useful to investigate the inner workings of a binary
Yes, ghidra exports were in the archive since first commit, however with decompiling/disassembling ARM binaries/libraries, there is problem, that the type of function arguments and return type cannot be detected automatically. I'm currently investigating, how to determine specific data types, because there is no chance all the relevant functions work only with int32_t arguments
If you've got any hints on this topic, i'd be glad for your input
I didn’t realise your end goal was decompilation and recompilation .
I don’t know about this implementation, but the version in the MD-380 and other TYT radios has hundreds of functions; so getting Everything to recompile will be a lot of work.
I am not even sure if it’s necessary work, since most people will just want to call the encode and decode functions and won’t care what goes on inside those functions.
The only thing, which I am not sure is fully understood with the TYT version of the codec is whether it’s possoble to change the tonal values of the compression , like the settings in radios like the Anytone 868 which use a hardware codec chip.
In the OpenGD77 firmware, which uses the TYT codec from the manufacturer firmware, for some unknown reason, the Rx audio sounds cleaner and chrisper than in the official TYT ( aka Radioddity ) firmware.
BTE. Baofeng also use the same codec, since all the firmware for all these Chinese DMR radios is written by a Chinese dev company, and not originally by the hardware manufacturers.
It's not that I want to do that. However since the source is Android shared library, it's compiled against Bionic instead of (g)LIBC and qemu-arm is not capable of running such environment.
So I have two choices, conduct all experiments on Android/ARM devices, or understand the inner workings of the library, decompile each function related to dvsi/ambe and try to work it out this way.
If you'd know of any way how to run Android compiled shared libraries in Linux/Windows environment, without actual Android VM, i'll gladly take that route.
In the end, I want to use the library and its functions to run encoding/decoding of the audio in linux x86 compatible environment
I assumed you wanted it mainly to run on the RPi.
I spoke to N4IRR on TAC 312 the other day and he told me that there was a wrapper to run the MD-380 codec binary, but I've tried emailing him to ask for more details but he hasn't got back to me :-(
You could try getting his email from QRZ.com and emailing him about it, in case that helps with your emulation on the X86 platform
I wrote him an email, but I suppose, he was talking about https://github.com/travisgoodspeed/md380tools/wiki/MD380-Emulator ?
I added udp encode and decode to the emulator. https://github.com/DVSwitch/md380tools/blob/master/emulator/md380-emu.c
It can be run on x86 using emu
qemu-arm md380tools/emulator/md380-emu -S 2470
N4IRR
@MichaelZingman
Hi Michael, We spoke on TAC 312 last week, (you where on the train) but I was no able to get in touch with you via email for some reason.
Anyway. Thanks for the link, because Kai DG4KLU is currently having some problems with the data produced by the TYT / Radioddity codec binary, so having other ways to compare the data could be useful.
Was also thinking I could add voice prompts to the Kai's OpenGD77 firmware, by encoding some synthesised speech using the codec in the emulator, and then storing the encoded data for each word e.g. "Channel", "0","1","2" etc in the external Flash memory.
And then playing that back by feeding the data into the firmware's decode system, as if the audio came from the DMR data stream.
I presume since the data is heavily compressed it would not take up too much space, and could be a useful feature for visually impaired operators.
VK3KYY
You should have no problem using the emulator to encode a set of samples. The encoder takes 160 bytes of 16 bit signed PCM and produces 7 bytes of AMBE. So given 50 samples of 20ms * 7 bytes = 350 bytes per second of speech you will need to store.
@MichaelZingman
Excellent
We should be able to add voice prompts to the OpenGD-77 firmware and use hardly any of the 1M byte external flash
Did you manage to get voice frames decoded through the source of the original app? When I ran it trying to initialize the decoder I got a segmentation fault.
@Nokoa i gave up my attempts and i'm now pursuing pure implementation using oboe sound library for android
if you want to pick up some knowledge or continue in the efforts, see beon branch https://github.com/OK-DMR/ambe-codec-p25/commits/beon specifically: https://github.com/OK-DMR/ambe-codec-p25/blob/beon/app/src/main/cpp/mmdvm.h#L186
If I remember correctly, and i kept no notes on my progress sincerely, this compiles, can be used to init encoder and decoder function in single instance, however from time to time, segmentation fault appears. And since I have no knowledge on p25 (and the library calls require this), i am unable to progress further.
Thank you! I didn't notice there was another branch. I did run this just to try and I noticed it is generating sound, but it almost sounds garbled, but with the sound of how to vocoder sounds. As if the vocoder is not setup with the correct rate. Is this a part that also didn't work for you?
@Nokoa ad branch: there was not, i just published it, realizing, someone is interested and might benefit from my experiments.
ad rate/config: I had trouble setting up classes for high-level PDUs, so i went for the low hanging fruit. However I was not able to either configure or feed the vocoder correct payloads, having only ever touched DMR, i hoped HALF_RATE is what I need, but i have exactly zero knowledge about vocoders, so i just modified the Oboe Android example and tried changing the params and the ways i fed it bytes from dmr vocoder bursts, and hoped for the best. I will appreciate any insight into this, sincerely trying to research this, i found very little, or it just didn't click for me
Also input data, https://github.com/OK-DMR/ambe-codec-p25/blob/beon/app/src/main/cpp/mmdvm.cpp#L16
was generated by this part of dmrlib-pcap-tool
(internally using transmission watcher), https://github.com/OK-DMR/ok-dmrlib/blob/master/okdmr/dmrlib/transmission/transmission_watcher.py#L40
using eg. dmrlib-pcap-tool --debug-vocoder-bytes -o dmr.pcapng
Absolutely not sure, this is the correct way to supply those to this implementation.
I have different one in the works,, that is based on manually merged imbe_vocoder and some other projects into compilable cpp library, see https://github.com/OK-DMR/ambe-codec-p25/tree/imbe/app/src/main/cpp again, just published this one can play the data, extracted the same way from dmr traffic, correctly, however i did not have time to pursue project completenes, the goal is to have basically mmdvm-hotspot in your android phone, consuming and producing homebrew (jonathan) protocol being able to operate voice (private, group, without PI) and text messaging services.
Do you have any interest in pursuing these topics? Let me know
I have never really worked with MMDVM. I am less on the Ham Radio side, more on the scanning side. Just looking for a better vocoder for my listening experience.
I just got it to decode the audio properly. I had to give the vocoder frames that are already error corrected. With the error bits removed. So not the full 72 bits, but 49 bits. I expect that DMR, P25 Half Rate, and NXDN should work with this. As they all use the same rate. I tested with DMR.
However I had to make the array of frames really short, otherwise the player caused the app to crash every time I tried to play.
All in all, the vocoder is working!!!
Yeah the implementation sucks, as i was not able to test and tune quality, never got to that phase actually. Can you share example array or diff of branch please?
Note that I also had to comment out the encode initialization function. Otherwise it was also causing it to crash. So I am only initializing the decoder. I tried to create another AmbeVocoder instance, to maybe be able to do both at the same time, but that also causes crashes.
I am getting errors such as
W/libc: Access denied finding property "sys.perf.boostopt"
or
A/libc: Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 29206 (binder:29174_4), pid 29174 (cz.okdmr.mmdvm)
and
I/scudo: Scudo ERROR: corrupted chunk header at address 0x2000076bb355850
That come with a crash.
I am also wondering how would you go about resetting the vocoder, so you can switch between the modes. Half rate, full rate, decode, encode. Also wondering whether there is a decode mode that does error correction and receives the full 72 bits for half rate mode.
In addition whether it's actually possible to decode multiple calls at the same time, which seems like it might be fast enough to do now. However I believe that at some instances the vocoder looks at the previous frames to make certain decisions, so mixing multiple call may cause issues?
On the hardware devices depending on the version 3000/3003, you can only do a limited number of channels, with a limited numbers of frames fed to the device at any given time.
This is some Tait DMR. I am only able to play a small part of this. Anything long causes a crash.
unsigned char const voicedata[][7] = {
{216, 33, 148, 130, 33, 33, 0},
{168, 22, 247, 30, 204, 111, 0},
{216, 21, 32, 207, 74, 82, 0},
{216, 41, 109, 184, 10, 237, 0},
{170, 40, 149, 162, 72, 82, 0},
{71, 58, 53, 3, 159, 238, 0},
{69, 64, 51, 142, 111, 157, 0},
{72, 27, 101, 2, 142, 73, 0},
{232, 33, 244, 79, 225, 248, 0},
{232, 49, 39, 168, 1, 69, 0},
{174, 151, 33, 239, 220, 62, 0},
{41, 90, 60, 131, 187, 11, 0},
{232, 97, 117, 139, 13, 37, 0},
{94, 58, 55, 102, 204, 98, 0},
{30, 10, 168, 133, 108, 78, 0},
{232, 33, 213, 139, 143, 84, 0},
{91, 99, 221, 242, 4, 73, 0},
{183, 132, 53, 138, 223, 223, 0},
{176, 225, 39, 162, 22, 197, 0},
{176, 217, 36, 138, 72, 11, 0},
{162, 197, 117, 14, 13, 158, 0},
{161, 185, 117, 217, 78, 37, 0},
{162, 133, 217, 175, 238, 29, 0},
{165, 135, 116, 171, 220, 121, 0},
{165, 155, 149, 30, 152, 21, 0},
{145, 219, 32, 175, 212, 18, 0},
{144, 217, 117, 45, 11, 13, 0},
{144, 219, 85, 57, 132, 134, 0},
{144, 189, 116, 181, 196, 81, 0},
{146, 157, 48, 105, 37, 122, 0},
{162, 30, 218, 67, 64, 186, 0},
{160, 199, 53, 239, 98, 122, 0},
{160, 209, 53, 125, 12, 49, 0},
{160, 178, 93, 47, 15, 199, 0},
{176, 177, 49, 46, 98, 102, 0},
{178, 151, 61, 58, 134, 246, 0},
{196, 90, 56, 223, 16, 251, 0},
{200, 24, 234, 34, 192, 61, 0},
{168, 42, 229, 83, 143, 206, 0},
{186, 67, 240, 207, 96, 240, 0},
{200, 227, 117, 95, 194, 65, 0},
{200, 185, 249, 174, 139, 55, 0},
{150, 89, 66, 164, 107, 233, 0},
{150, 124, 145, 219, 184, 48, 0},
{144, 124, 181, 147, 169, 122, 0},
{144, 94, 36, 209, 99, 230, 0},
{144, 110, 215, 144, 6, 79, 0},
{165, 93, 45, 210, 210, 77, 0},
{165, 58, 61, 90, 15, 87, 0},
{182, 43, 61, 31, 136, 5, 0},
{184, 35, 1, 32, 169, 98, 0},
{152, 113, 241, 71, 66, 181, 0},
{168, 82, 96, 153, 74, 68, 0},
{184, 91, 242, 158, 137, 37, 0},
{184, 112, 37, 97, 65, 42, 0},
{168, 133, 100, 205, 136, 15, 0},
{167, 172, 85, 58, 241, 51, 0},
{160, 180, 37, 46, 169, 21, 0},
{160, 185, 5, 132, 162, 14, 0},
{160, 144, 49, 5, 139, 33, 0},
{160, 165, 149, 26, 164, 36, 0},
{160, 157, 12, 75, 140, 34, 0},
{162, 77, 179, 80, 196, 66, 0},
{162, 133, 114, 128, 68, 190, 0},
{162, 105, 152, 195, 66, 62, 0},
{161, 122, 114, 78, 35, 179, 0},
{161, 107, 17, 205, 195, 173, 0},
{162, 137, 80, 190, 34, 66, 0},
{162, 120, 87, 57, 43, 3, 0},
{162, 117, 21, 109, 10, 25, 0},
{161, 150, 89, 88, 226, 37, 0},
{161, 155, 17, 58, 204, 32, 0},
{162, 168, 240, 62, 173, 231, 0},
{161, 154, 1, 98, 44, 104, 0},
{161, 159, 148, 162, 37, 200, 0},
{160, 148, 113, 67, 109, 224, 0},
{160, 141, 145, 66, 4, 113, 0},
{160, 138, 145, 82, 109, 98, 0},
{160, 143, 1, 70, 100, 224, 0},
{161, 151, 16, 170, 164, 59, 0},
{162, 149, 49, 104, 180, 61, 0},
{162, 145, 50, 84, 158, 71, 0},
{180, 41, 58, 0, 216, 81, 0},
{180, 58, 183, 168, 176, 251, 0},
{153, 130, 164, 255, 30, 119, 0},
{46, 179, 13, 46, 214, 102, 0},
{12, 12, 37, 38, 120, 199, 0},
{232, 41, 193, 132, 199, 180, 0},
{234, 129, 112, 122, 78, 105, 0},
{12, 71, 29, 139, 69, 119, 0},
{108, 225, 85, 194, 5, 208, 0},
{183, 169, 180, 26, 158, 79, 0},
{176, 203, 4, 47, 116, 81, 0},
{176, 169, 53, 62, 10, 167, 0},
{179, 58, 58, 248, 74, 63, 0},
{163, 61, 123, 138, 198, 154, 0},
{162, 91, 22, 74, 14, 30, 0},
{160, 197, 220, 102, 124, 69, 0},
{160, 165, 53, 163, 69, 62, 0},
{160, 154, 121, 175, 141, 90, 0},
{160, 119, 60, 175, 172, 28, 0},
{161, 57, 50, 202, 142, 93, 0},
{161, 95, 120, 73, 206, 174, 0},
{162, 107, 25, 72, 68, 63, 0},
{162, 77, 120, 166, 13, 54, 0},
{162, 75, 59, 187, 78, 165, 0},
{178, 59, 27, 184, 8, 39, 0},
{178, 75, 50, 174, 67, 76, 0},
{194, 63, 89, 75, 162, 130, 0},
{213, 39, 53, 226, 238, 17, 0},
{41, 36, 251, 164, 94, 211, 0},
{232, 35, 180, 168, 135, 141, 0},
{216, 24, 245, 66, 78, 58, 0},
{184, 34, 115, 173, 136, 51, 0},
{120, 42, 186, 152, 46, 119, 0},
{135, 47, 26, 74, 144, 60, 0},
{135, 57, 97, 16, 74, 255, 0},
{45, 37, 192, 98, 119, 96, 0},
{170, 49, 109, 179, 6, 107, 0},
{232, 61, 101, 192, 199, 229, 0},
{186, 205, 69, 178, 72, 243, 0},
{30, 48, 87, 153, 68, 68, 0},
{110, 161, 21, 218, 47, 247, 0},
{177, 201, 84, 0, 149, 217, 0},
{176, 197, 39, 146, 168, 116, 0},
{160, 184, 117, 146, 143, 214, 0},
{176, 185, 36, 18, 136, 212, 0},
{176, 185, 85, 30, 72, 23, 0},
{161, 179, 20, 146, 135, 215, 0},
{160, 185, 85, 178, 207, 179, 0},
{160, 162, 158, 32, 142, 56, 0},
{176, 151, 23, 102, 200, 123, 0},
{176, 135, 25, 112, 129, 209, 0},
{176, 77, 43, 198, 170, 74, 0},
{180, 56, 178, 151, 75, 117, 0},
{180, 61, 179, 184, 229, 113, 0},
{182, 61, 73, 12, 6, 127, 0},
{184, 60, 151, 243, 6, 85, 0},
{200, 143, 80, 158, 143, 17, 0},
{167, 192, 83, 60, 144, 22, 0},
{163, 224, 213, 148, 129, 67, 0},
{162, 213, 68, 140, 216, 201, 0},
{166, 193, 151, 194, 144, 90, 0},
{162, 193, 189, 154, 8, 131, 0},
{162, 217, 117, 10, 64, 182, 0},
{146, 205, 189, 189, 54, 49, 0},
{160, 202, 121, 125, 64, 115, 0},
{160, 200, 117, 191, 129, 133, 0},
{160, 203, 85, 30, 74, 71, 0},
{160, 179, 29, 138, 130, 211, 0},
{160, 209, 151, 138, 131, 252, 0},
{163, 198, 168, 68, 146, 3, 0},
{160, 171, 145, 151, 172, 36, 0},
{160, 78, 33, 72, 38, 110, 0},
{162, 46, 197, 83, 78, 63, 0},
{184, 49, 54, 136, 138, 121, 0},
{167, 69, 60, 173, 149, 20, 0},
{166, 76, 68, 243, 104, 122, 0},
{150, 110, 49, 187, 237, 246, 0},
{146, 126, 128, 180, 52, 115, 0},
{146, 154, 81, 195, 84, 106, 0},
{146, 160, 49, 120, 116, 55, 0},
{146, 169, 50, 164, 213, 152, 0},
{147, 175, 104, 155, 206, 115, 0},
{144, 175, 241, 167, 143, 34, 0},
{144, 205, 235, 220, 199, 251, 0},
{144, 159, 179, 180, 166, 54, 0},
{160, 169, 121, 218, 232, 117, 0},
{163, 153, 92, 98, 185, 137, 0},
{164, 72, 16, 164, 154, 89, 0},
{163, 61, 153, 75, 204, 163, 0},
{163, 104, 81, 173, 234, 79, 0},
{162, 167, 17, 104, 160, 125, 0},
{161, 173, 33, 106, 137, 120, 0},
{161, 194, 149, 24, 161, 115, 0},
{160, 164, 116, 43, 56, 72, 0},
{160, 169, 145, 169, 10, 233, 0},
{162, 156, 65, 171, 42, 186, 0},
{160, 157, 232, 99, 120, 26, 0},
{160, 148, 176, 105, 97, 142, 0},
{166, 155, 51, 100, 98, 175, 0},
{166, 138, 214, 226, 130, 105, 0},
{183, 25, 186, 11, 8, 63, 0},
{87, 63, 194, 18, 199, 60, 0},
{86, 39, 86, 128, 6, 59, 0},
{92, 145, 5, 103, 138, 98, 0},
{119, 43, 192, 10, 21, 139, 0},
{117, 35, 5, 113, 204, 33, 0},
{116, 57, 101, 123, 21, 135, 0},
{117, 41, 148, 0, 204, 120, 0},
{168, 69, 97, 207, 96, 108, 0},
{168, 245, 29, 244, 232, 242, 0},
{163, 211, 145, 138, 137, 88, 0},
{161, 201, 71, 138, 138, 62, 0},
{160, 137, 93, 155, 172, 231, 0},
{184, 45, 109, 46, 229, 245, 0},
{184, 25, 248, 94, 172, 40, 0},
{232, 58, 176, 239, 135, 119, 0},
{142, 59, 27, 228, 54, 65, 0},
{232, 21, 244, 9, 198, 31, 0},
{136, 32, 237, 79, 233, 227, 0},
{136, 57, 240, 86, 201, 218, 0},
{232, 98, 101, 235, 138, 115, 0},
{200, 130, 161, 197, 193, 92, 0},
{200, 121, 241, 51, 193, 17, 0},
{167, 109, 127, 177, 208, 122, 0},
{160, 239, 55, 90, 193, 39, 0},
{160, 171, 179, 231, 234, 120, 0},
{160, 157, 247, 72, 202, 83, 0},
{160, 171, 38, 223, 196, 49, 0},
{160, 154, 177, 174, 197, 31, 0},
{160, 143, 41, 166, 76, 11, 0},
{160, 154, 121, 66, 229, 150, 0},
{160, 143, 39, 169, 197, 49, 0},
{160, 125, 112, 238, 174, 10, 0},
{160, 126, 97, 73, 143, 5, 0},
{176, 105, 20, 236, 225, 26, 0},
{179, 111, 209, 84, 218, 3, 0},
{200, 69, 115, 96, 172, 195, 0},
{216, 27, 109, 27, 15, 102, 0},
{168, 41, 69, 171, 74, 95, 0},
{130, 39, 121, 180, 72, 34, 0},
{132, 53, 69, 56, 33, 19, 0},
{132, 39, 117, 92, 200, 31, 0},
{132, 50, 44, 162, 177, 19, 0},
{136, 35, 81, 9, 9, 83, 0},
{152, 41, 95, 45, 192, 93, 0},
{184, 43, 100, 234, 104, 120, 0},
{184, 57, 60, 30, 133, 36, 0},
{184, 35, 84, 104, 204, 90, 0},
{184, 40, 188, 231, 197, 206, 0},
{234, 130, 225, 80, 47, 160, 0},
{126, 207, 112, 169, 162, 119, 0},
{232, 98, 61, 207, 142, 39, 0},
{151, 161, 41, 15, 52, 109, 0},
{145, 226, 190, 158, 116, 18, 0},
{144, 229, 168, 130, 197, 101, 0},
{144, 200, 212, 164, 165, 106, 0},
{144, 61, 186, 108, 134, 25, 0},
{160, 107, 23, 131, 128, 149, 0},
{163, 91, 19, 169, 138, 219, 0},
{163, 61, 88, 28, 12, 52, 0},
{166, 79, 216, 86, 230, 164, 0},
{161, 137, 148, 91, 86, 130, 0},
{161, 233, 244, 111, 196, 15, 0},
{161, 143, 45, 78, 7, 21, 0},
{163, 60, 119, 144, 135, 18, 0},
{164, 121, 176, 75, 158, 60, 0},
{166, 123, 32, 64, 103, 244, 0},
{182, 22, 27, 153, 234, 145, 0},
{183, 34, 176, 41, 236, 55, 0},
{234, 129, 69, 70, 139, 250, 0},
{127, 172, 201, 100, 66, 5, 0},
{162, 222, 33, 191, 26, 21, 0},
{163, 210, 49, 40, 101, 162, 0},
{160, 209, 149, 21, 165, 80, 0},
{160, 226, 57, 156, 164, 54, 0},
{160, 194, 81, 6, 228, 194, 0},
{163, 202, 126, 48, 132, 208, 0},
{163, 171, 52, 251, 148, 126, 0},
{182, 43, 51, 136, 8, 208, 0},
{166, 201, 184, 243, 183, 236, 0},
{164, 132, 184, 74, 142, 84, 0},
{176, 54, 59, 75, 73, 203, 0},
{181, 75, 48, 144, 193, 21, 0},
{181, 68, 177, 194, 0, 95, 0},
{181, 61, 220, 62, 8, 20, 0},
{183, 67, 160, 129, 231, 133, 0},
{199, 49, 213, 49, 208, 107, 0},
{181, 48, 165, 52, 196, 211, 0},
{184, 123, 96, 214, 106, 114, 0},
{168, 127, 185, 9, 128, 23, 0},
{167, 239, 54, 250, 80, 76, 0},
{164, 73, 56, 161, 58, 8, 0},
{161, 197, 216, 173, 146, 42, 0},
{160, 187, 52, 238, 12, 47, 0},
{163, 166, 115, 83, 230, 103, 0},
{163, 78, 249, 169, 142, 43, 0},
{182, 97, 164, 135, 73, 213, 0},
{184, 83, 0, 120, 129, 43, 0},
{232, 99, 145, 205, 192, 80, 0},
{232, 41, 236, 67, 171, 166, 0},
{200, 41, 149, 21, 165, 225, 0},
{200, 37, 116, 66, 204, 69, 0},
{200, 41, 69, 172, 165, 228, 0},
{151, 199, 244, 143, 210, 15, 0},
{145, 248, 22, 115, 18, 103, 0},
{144, 225, 53, 138, 101, 242, 0},
{145, 225, 161, 143, 15, 14, 0},
{144, 208, 120, 130, 94, 28, 0},
{160, 213, 112, 152, 72, 231, 0},
{160, 211, 48, 158, 105, 116, 0},
{161, 181, 52, 31, 106, 71, 0},
{161, 149, 48, 63, 3, 103, 0},
{163, 63, 56, 72, 154, 23, 0},
{163, 105, 187, 175, 152, 38, 0},
{162, 90, 49, 157, 0, 5, 0},
{164, 58, 59, 182, 89, 0, 0},
{165, 46, 114, 41, 136, 107, 0},
{166, 57, 232, 131, 165, 156, 0},
{60, 169, 197, 100, 253, 103, 0},
{228, 48, 101, 79, 214, 60, 0},
{135, 33, 20, 140, 28, 119, 0},
{133, 50, 169, 87, 236, 190, 0},
{136, 107, 161, 86, 132, 83, 0},
{89, 138, 209, 248, 228, 224, 0},
{168, 83, 221, 14, 15, 54, 0},
{168, 83, 116, 89, 142, 73, 0},
{168, 83, 45, 179, 135, 3, 0},
{232, 89, 97, 79, 3, 110, 0},
{184, 74, 117, 236, 174, 45, 0},
{200, 65, 241, 187, 204, 68, 0},
{216, 67, 20, 169, 3, 53, 0},
{216, 83, 180, 137, 130, 99, 0},
{152, 51, 89, 207, 43, 63, 0},
{152, 75, 165, 170, 175, 105, 0},
{136, 54, 209, 31, 142, 115, 0},
{136, 73, 197, 146, 64, 208, 0},
{120, 53, 253, 111, 139, 148, 0},
{104, 41, 60, 19, 206, 121, 0},
{104, 40, 226, 0, 142, 20, 0},
{152, 40, 231, 153, 175, 215, 0},
{136, 51, 124, 175, 66, 35, 0},
{136, 41, 173, 191, 232, 28, 0},
{120, 51, 180, 64, 71, 135, 0},
{116, 61, 108, 143, 86, 54, 0},
{120, 41, 244, 30, 79, 38, 0},
{151, 156, 241, 240, 55, 200, 0},
{160, 251, 25, 125, 64, 115, 0},
{160, 249, 245, 39, 192, 199, 0},
{144, 210, 125, 44, 15, 87, 0},
{160, 233, 121, 40, 160, 119, 0},
{160, 211, 21, 44, 128, 60, 0},
{144, 203, 52, 106, 143, 108, 0},
{144, 226, 123, 108, 38, 121, 0},
{161, 199, 48, 254, 0, 185, 0},
{161, 191, 223, 183, 137, 4, 0},
{163, 60, 248, 207, 82, 47, 0},
{184, 51, 163, 46, 161, 64, 0},
{184, 123, 197, 234, 73, 227, 0},
{73, 72, 0, 245, 80, 99, 0},
{216, 43, 37, 89, 239, 60, 0},
{122, 120, 133, 98, 194, 98, 0},
{151, 92, 181, 154, 30, 47, 0},
{150, 108, 124, 220, 82, 117, 0},
{133, 110, 36, 205, 29, 237, 0},
{131, 142, 217, 220, 74, 109, 0},
{131, 140, 208, 193, 171, 122, 0},
{128, 157, 209, 83, 67, 163, 0},
{128, 168, 112, 57, 98, 36, 0},
{130, 150, 242, 80, 101, 240, 0},
{134, 75, 234, 11, 166, 27, 0},
{135, 65, 245, 23, 100, 116, 0},
{232, 83, 173, 206, 71, 150, 0},
{183, 153, 165, 169, 85, 99, 0},
{134, 204, 83, 244, 146, 91, 0},
{129, 156, 112, 80, 116, 242, 0},
{128, 191, 71, 178, 70, 255, 0},
{128, 133, 52, 81, 174, 2, 0},
{144, 143, 38, 227, 129, 57, 0},
{144, 14, 34, 15, 107, 40, 0},
{150, 43, 89, 128, 132, 36, 0},
{152, 43, 35, 47, 138, 99, 0},
{151, 231, 20, 248, 57, 249, 0},
{150, 225, 21, 38, 12, 103, 0},
{147, 211, 149, 138, 173, 250, 0},
{145, 233, 65, 192, 69, 187, 0},
{144, 197, 9, 193, 14, 72, 0},
{144, 208, 44, 146, 231, 245, 0},
{144, 183, 29, 24, 15, 226, 0},
{144, 172, 67, 118, 78, 71, 0},
{160, 124, 119, 110, 224, 250, 0},
{161, 47, 155, 192, 73, 25, 0},
{164, 61, 190, 147, 18, 113, 0},
{166, 46, 115, 172, 3, 38, 0},
{125, 79, 153, 238, 242, 179, 0},
{151, 185, 144, 31, 88, 95, 0},
{144, 196, 215, 113, 136, 193, 0},
{144, 210, 93, 38, 64, 247, 0},
{144, 157, 85, 146, 136, 115, 0},
{128, 181, 52, 146, 135, 241, 0},
{144, 184, 45, 170, 136, 235, 0},
{144, 200, 47, 189, 192, 119, 0},
{144, 205, 248, 251, 97, 110, 0},
{147, 189, 240, 171, 18, 223, 0},
{148, 127, 240, 133, 20, 113, 0},
{150, 139, 179, 80, 165, 176, 0},
{150, 127, 112, 78, 93, 103, 0},
{147, 159, 177, 226, 124, 89, 0},
{145, 137, 88, 175, 28, 79, 0},
{144, 137, 48, 57, 141, 229, 0},
{144, 154, 182, 239, 236, 46, 0},
{144, 143, 7, 171, 70, 47, 0},
{144, 77, 91, 150, 198, 246, 0},
{145, 107, 184, 168, 6, 115, 0},
{145, 90, 57, 162, 7, 223, 0},
{144, 75, 24, 146, 15, 135, 0},
{162, 75, 155, 162, 96, 92, 0},
{162, 60, 121, 168, 72, 180, 0},
{163, 60, 252, 66, 57, 3, 0},
{165, 79, 211, 111, 130, 29, 0},
{166, 55, 168, 45, 205, 38, 0},
{168, 80, 231, 73, 77, 225, 0},
{184, 67, 177, 158, 130, 117, 0},
{216, 51, 80, 206, 129, 113, 0},
{232, 45, 148, 115, 15, 230, 0},
{30, 23, 214, 95, 214, 95, 0},
{232, 16, 241, 140, 239, 99, 0},
{186, 113, 116, 121, 0, 102, 0},
{30, 18, 12, 34, 66, 114, 0},
{232, 23, 211, 152, 135, 67, 0},
{232, 26, 85, 85, 239, 178, 0},
{168, 43, 9, 78, 64, 30, 0},
{168, 23, 208, 137, 104, 100, 0},
{136, 38, 240, 92, 0, 69, 0},
{136, 34, 125, 51, 160, 51, 0},
{184, 16, 248, 98, 8, 156, 0},
{168, 45, 101, 31, 161, 163, 0},
{168, 41, 102, 222, 72, 55, 0},
{183, 241, 21, 146, 147, 229, 0},
{177, 189, 85, 138, 121, 255, 0},
{161, 201, 33, 18, 6, 85, 0},
{160, 209, 183, 31, 132, 228, 0},
{160, 184, 116, 186, 140, 215, 0},
{160, 195, 21, 203, 98, 25, 0},
{160, 179, 17, 158, 99, 199, 0},
{160, 179, 20, 155, 67, 0, 0},
{164, 201, 36, 206, 74, 14, 0},
{160, 203, 81, 146, 43, 212, 0},
{160, 200, 119, 50, 196, 227, 0},
{162, 173, 38, 112, 150, 3, 0},
{164, 62, 34, 207, 87, 205, 0},
{182, 44, 123, 194, 169, 254, 0},
{182, 27, 216, 1, 234, 119, 0},
{166, 89, 179, 207, 132, 29, 0},
{166, 58, 56, 42, 29, 254, 0},
{163, 79, 59, 174, 4, 39, 0},
{163, 39, 24, 75, 78, 195, 0},
{26, 25, 242, 205, 137, 225, 0},
{168, 18, 101, 183, 206, 74, 0},
{168, 37, 252, 170, 231, 19, 0},
{152, 32, 241, 151, 67, 223, 0},
{232, 26, 100, 173, 172, 18, 0},
{152, 23, 41, 93, 142, 225, 0},
{152, 33, 176, 22, 70, 196, 0},
{152, 26, 165, 159, 110, 33, 0},
{184, 41, 210, 217, 130, 85, 0},
{168, 16, 241, 190, 43, 82, 0},
{168, 18, 188, 163, 138, 35, 0},
{168, 46, 103, 76, 131, 106, 0},
};
Wonderful @Nokoa great work SIGABRT when trying to use both encode and decode within single instance happened to me as well, but it was not very certain, sometimes it went through, sometimes not. Also the wrapping C++ code is not very elegant, tested, and so on.
Regarding resetting, we're in high-level programming, you can create multiple instances of the class probably. There are actually classes, that has self-explanatory names, such as VoiceDecoderAmbeFullRate
, see: https://github.com/OK-DMR/ambe-codec-p25/blob/master/lib/liblib-core.so.ghidra-auto-generated.h#L1578
I believe, you should just instantiate VoiceDecoderAmbeHalfRate for decoding, VoiceEncoderAmbeHalfRate for encoding, one will work with incoming queue from radio network, second will be fed samples from microphone and used to construct voice bursts. However for such high-level APIs, they require session/state objects, and these interfaces are shared (c++ class is implementing the same interface as java class), and they work with high-level PDUs from P25 protocol, maybe we don't want to do this?
eg.
> objdump -TC liblib-core.so | grep -i VoiceDecoderAmbeHalfRate
000000000019e8ac g DF .text 0000000000000078 Base BeOn::VoiceDecoderAmbeHalfRate::~VoiceDecoderAmbeHalfRate()
00000000001a003c g DF .text 0000000000000138 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu4V_2(BeOn::IVoiceDecrypter*, int*)
000000000019f4e0 g DF .text 00000000000005bc Base BeOn::VoiceDecoderAmbeHalfRate::checkCryptoSync(BeOn::IVoiceDecrypter*, unsigned char)
00000000003a4735 g DO .rodata 0000000000000022 Base typeinfo name for BeOn::VoiceDecoderAmbeHalfRate
000000000019e83c g DF .text 0000000000000070 Base BeOn::VoiceDecoderAmbeHalfRate::~VoiceDecoderAmbeHalfRate()
00000000001a03e4 g DF .text 0000000000000258 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu2V(BeOn::IVoiceDecrypter*, int*)
000000000019e83c g DF .text 0000000000000070 Base BeOn::VoiceDecoderAmbeHalfRate::~VoiceDecoderAmbeHalfRate()
0000000000428d30 g DO .data.rel.ro 0000000000000048 Base vtable for BeOn::VoiceDecoderAmbeHalfRate
000000000019e924 g DF .text 00000000000003b4 Base BeOn::VoiceDecoderAmbeHalfRate::initDecoder()
0000000000428d78 g DO .data.rel.ro 0000000000000018 Base typeinfo for BeOn::VoiceDecoderAmbeHalfRate
00000000001a02ac g DF .text 0000000000000138 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu4V_4(BeOn::IVoiceDecrypter*, int*)
000000000019f338 g DF .text 00000000000001a8 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu(BeOn::IVoiceDecrypter*, int*, unsigned char)
000000000019e768 g DF .text 00000000000000d4 Base BeOn::VoiceDecoderAmbeHalfRate::VoiceDecoderAmbeHalfRate(BeOn::IBeOnExtendedCore*, BeOn::VoiceProcessor*, IBeOnVocoder*)
00000000001a063c w DF .text 0000000000000008 Base BeOn::VoiceDecoderAmbeHalfRate::getVocoderType()
000000000019fdc0 g DF .text 00000000000000e4 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu4V_U(BeOn::IVoiceDecrypter*, int*)
00000000001a0644 w DF .text 0000000000000024 Base BeOn::VoiceDecoderAmbeHalfRate::getSilenceBufferSize()
000000000019fea4 g DF .text 0000000000000198 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu4V_1(BeOn::IVoiceDecrypter*, int*)
00000000001a0174 g DF .text 0000000000000138 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu4V_3(BeOn::IVoiceDecrypter*, int*)
000000000019fa9c g DF .text 00000000000000ac Base BeOn::VoiceDecoderAmbeHalfRate::decryptDummyPdu(BeOn::IVoiceDecrypter*, unsigned char)
000000000019ecd8 g DF .text 0000000000000660 Base BeOn::VoiceDecoderAmbeHalfRate::decodePdu(unsigned char*, int)
000000000019fb48 g DF .text 0000000000000278 Base BeOn::VoiceDecoderAmbeHalfRate::tryToGetCryptoSync(BeOn::IVoiceDecrypter*, unsigned char, int)
000000000019e768 g DF .text 00000000000000d4 Base BeOn::VoiceDecoderAmbeHalfRate::VoiceDecoderAmbeHalfRate(BeOn::IBeOnExtendedCore*, BeOn::VoiceProcessor*, IBeOnVocoder*)
where AmbeVocoder is much simpler
> objdump -TC liblib-core.so | grep AmbeVocoder
0000000000428170 g DO .data.rel.ro 0000000000000080 Base vtable for BeOn::AmbeVocoder
0000000000428200 g DO .data.rel.ro 0000000000000018 Base typeinfo for BeOn::AmbeVocoder
00000000003a0fb8 g DO .rodata 0000000000000015 Base typeinfo name for BeOn::AmbeVocoder
000000000017c514 g DF .text 000000000000010c Base BeOn::AmbeVocoder::decodeInit()
000000000017cf44 w DF .text 0000000000000008 Base BeOn::AmbeVocoder::getType() const
000000000017c100 g DF .text 00000000000001f8 Base BeOn::AmbeVocoder::AmbeVocoder(short)
000000000017cd50 g DF .text 00000000000001d0 Base BeOn::AmbeVocoder::unpackBytesToBits(short*, unsigned char const*, int, int)
000000000017c100 g DF .text 00000000000001f8 Base BeOn::AmbeVocoder::AmbeVocoder(short)
000000000017c8d4 g DF .text 00000000000001f0 Base BeOn::AmbeVocoder::packBitsToBytes(short*, unsigned char*, int, int)
000000000017cf54 w DF .text 0000000000000008 Base BeOn::AmbeVocoder::getMaxEncodedFrameLengthInBytes() const
000000000017c3e4 g DF .text 0000000000000024 Base BeOn::AmbeVocoder::~AmbeVocoder()
000000000017c408 g DF .text 000000000000010c Base BeOn::AmbeVocoder::encodeInit()
000000000017c2f8 g DF .text 00000000000000ec Base BeOn::AmbeVocoder::~AmbeVocoder()
000000000017cf20 g DF .text 0000000000000014 Base BeOn::AmbeVocoder::enablePostDecodeCompression(float, float, float, float)
000000000017c2f8 g DF .text 00000000000000ec Base BeOn::AmbeVocoder::~AmbeVocoder()
000000000017cf5c w DF .text 0000000000000008 Base BeOn::AmbeVocoder::getSampleRate() const
000000000017cf4c w DF .text 0000000000000008 Base BeOn::AmbeVocoder::getMaxFrameLength() const
000000000017cac4 g DF .text 000000000000028c Base BeOn::AmbeVocoder::decode(unsigned char const*, int, short*)
000000000017c620 g DF .text 00000000000002b4 Base BeOn::AmbeVocoder::encode(short const*, int, unsigned char*)
000000000017cf34 g DF .text 0000000000000010 Base BeOn::AmbeVocoder::disablePostDecodeCompression()
And for the crash, i'd suspect my code handling the samples is faulty, you can feed it all samples before starting playback, i've not yet tried continuous buffer handling with jitter, because again, this is not something i understand in-depth. Do you have any reading tips on that topic, i could read up? Something like "if you want to encode speech, you need to sample pcm s16 data 60ns each and supply these 7 bytes to vocoder and merge 6 encoded voice samples into single vocoder dmr tier-ii burst in this way" or "what the vocoder dmr burst actually contains in terms of ambe codec"
Also, is/should vocoder be deterministic, eg. if I have AMBE data, i decode them, encode them, do i get the same AMBE data i started with? Can those be compared in terms of content, BER, FEC or any other params? I'd like some quality estimation or comparison, to be able to fine-tune the implementation.
Wonderful @Nokoa great work
SIGABRT when trying to use both encode and decode within single instance happened to me as well, but it was not very certain, sometimes it went through, sometimes not. Also the wrapping C++ code is not very elegant, tested, and so on.
Regarding resetting, we're in high-level programming, you can create multiple instances of the class probably. There are actually classes, that has self-explanatory names, such as
VoiceDecoderAmbeFullRate
, see: https://github.com/OK-DMR/ambe-codec-p25/blob/master/lib/liblib-core.so.ghidra-auto-generated.h#L1578I believe, you should just instantiate VoiceDecoderAmbeHalfRate for decoding, VoiceEncoderAmbeHalfRate for encoding, one will work with incoming queue from radio network, second will be fed samples from microphone and used to construct voice bursts.
However for such high-level APIs, they require session/state objects, and these interfaces are shared (c++ class is implementing the same interface as java class), and they work with high-level PDUs from P25 protocol, maybe we don't want to do this?
eg.
> objdump -TC liblib-core.so | grep -i VoiceDecoderAmbeHalfRate 000000000019e8ac g DF .text 0000000000000078 Base BeOn::VoiceDecoderAmbeHalfRate::~VoiceDecoderAmbeHalfRate() 00000000001a003c g DF .text 0000000000000138 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu4V_2(BeOn::IVoiceDecrypter*, int*) 000000000019f4e0 g DF .text 00000000000005bc Base BeOn::VoiceDecoderAmbeHalfRate::checkCryptoSync(BeOn::IVoiceDecrypter*, unsigned char) 00000000003a4735 g DO .rodata 0000000000000022 Base typeinfo name for BeOn::VoiceDecoderAmbeHalfRate 000000000019e83c g DF .text 0000000000000070 Base BeOn::VoiceDecoderAmbeHalfRate::~VoiceDecoderAmbeHalfRate() 00000000001a03e4 g DF .text 0000000000000258 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu2V(BeOn::IVoiceDecrypter*, int*) 000000000019e83c g DF .text 0000000000000070 Base BeOn::VoiceDecoderAmbeHalfRate::~VoiceDecoderAmbeHalfRate() 0000000000428d30 g DO .data.rel.ro 0000000000000048 Base vtable for BeOn::VoiceDecoderAmbeHalfRate 000000000019e924 g DF .text 00000000000003b4 Base BeOn::VoiceDecoderAmbeHalfRate::initDecoder() 0000000000428d78 g DO .data.rel.ro 0000000000000018 Base typeinfo for BeOn::VoiceDecoderAmbeHalfRate 00000000001a02ac g DF .text 0000000000000138 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu4V_4(BeOn::IVoiceDecrypter*, int*) 000000000019f338 g DF .text 00000000000001a8 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu(BeOn::IVoiceDecrypter*, int*, unsigned char) 000000000019e768 g DF .text 00000000000000d4 Base BeOn::VoiceDecoderAmbeHalfRate::VoiceDecoderAmbeHalfRate(BeOn::IBeOnExtendedCore*, BeOn::VoiceProcessor*, IBeOnVocoder*) 00000000001a063c w DF .text 0000000000000008 Base BeOn::VoiceDecoderAmbeHalfRate::getVocoderType() 000000000019fdc0 g DF .text 00000000000000e4 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu4V_U(BeOn::IVoiceDecrypter*, int*) 00000000001a0644 w DF .text 0000000000000024 Base BeOn::VoiceDecoderAmbeHalfRate::getSilenceBufferSize() 000000000019fea4 g DF .text 0000000000000198 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu4V_1(BeOn::IVoiceDecrypter*, int*) 00000000001a0174 g DF .text 0000000000000138 Base BeOn::VoiceDecoderAmbeHalfRate::decryptAndDecodeLdu4V_3(BeOn::IVoiceDecrypter*, int*) 000000000019fa9c g DF .text 00000000000000ac Base BeOn::VoiceDecoderAmbeHalfRate::decryptDummyPdu(BeOn::IVoiceDecrypter*, unsigned char) 000000000019ecd8 g DF .text 0000000000000660 Base BeOn::VoiceDecoderAmbeHalfRate::decodePdu(unsigned char*, int) 000000000019fb48 g DF .text 0000000000000278 Base BeOn::VoiceDecoderAmbeHalfRate::tryToGetCryptoSync(BeOn::IVoiceDecrypter*, unsigned char, int) 000000000019e768 g DF .text 00000000000000d4 Base BeOn::VoiceDecoderAmbeHalfRate::VoiceDecoderAmbeHalfRate(BeOn::IBeOnExtendedCore*, BeOn::VoiceProcessor*, IBeOnVocoder*)
where AmbeVocoder is much simpler
> objdump -TC liblib-core.so | grep AmbeVocoder 0000000000428170 g DO .data.rel.ro 0000000000000080 Base vtable for BeOn::AmbeVocoder 0000000000428200 g DO .data.rel.ro 0000000000000018 Base typeinfo for BeOn::AmbeVocoder 00000000003a0fb8 g DO .rodata 0000000000000015 Base typeinfo name for BeOn::AmbeVocoder 000000000017c514 g DF .text 000000000000010c Base BeOn::AmbeVocoder::decodeInit() 000000000017cf44 w DF .text 0000000000000008 Base BeOn::AmbeVocoder::getType() const 000000000017c100 g DF .text 00000000000001f8 Base BeOn::AmbeVocoder::AmbeVocoder(short) 000000000017cd50 g DF .text 00000000000001d0 Base BeOn::AmbeVocoder::unpackBytesToBits(short*, unsigned char const*, int, int) 000000000017c100 g DF .text 00000000000001f8 Base BeOn::AmbeVocoder::AmbeVocoder(short) 000000000017c8d4 g DF .text 00000000000001f0 Base BeOn::AmbeVocoder::packBitsToBytes(short*, unsigned char*, int, int) 000000000017cf54 w DF .text 0000000000000008 Base BeOn::AmbeVocoder::getMaxEncodedFrameLengthInBytes() const 000000000017c3e4 g DF .text 0000000000000024 Base BeOn::AmbeVocoder::~AmbeVocoder() 000000000017c408 g DF .text 000000000000010c Base BeOn::AmbeVocoder::encodeInit() 000000000017c2f8 g DF .text 00000000000000ec Base BeOn::AmbeVocoder::~AmbeVocoder() 000000000017cf20 g DF .text 0000000000000014 Base BeOn::AmbeVocoder::enablePostDecodeCompression(float, float, float, float) 000000000017c2f8 g DF .text 00000000000000ec Base BeOn::AmbeVocoder::~AmbeVocoder() 000000000017cf5c w DF .text 0000000000000008 Base BeOn::AmbeVocoder::getSampleRate() const 000000000017cf4c w DF .text 0000000000000008 Base BeOn::AmbeVocoder::getMaxFrameLength() const 000000000017cac4 g DF .text 000000000000028c Base BeOn::AmbeVocoder::decode(unsigned char const*, int, short*) 000000000017c620 g DF .text 00000000000002b4 Base BeOn::AmbeVocoder::encode(short const*, int, unsigned char*) 000000000017cf34 g DF .text 0000000000000010 Base BeOn::AmbeVocoder::disablePostDecodeCompression()
And for the crash, i'd suspect my code handling the samples is faulty, you can feed it all samples before starting playback, i've not yet tried continuous buffer handling with jitter, because again, this is not something i understand in-depth.
Do you have any reading tips on that topic, i could read up? Something like "if you want to encode speech, you need to sample pcm s16 data 60ns each and supply these 7 bytes to vocoder and merge 6 encoded voice samples into single vocoder dmr tier-ii burst in this way" or "what the vocoder dmr burst actually contains in terms of ambe codec"
On the BeOn java decompile i do see that they have an interface for the AmbeVocoder same as what you did. I am not certain how to use the P25 specific one.
I did try to initialize 2 instances of AmbeVocoder, and tried reinitializing the one. Both led to errors.
I also tried to see if I can have Java pass the frame data to C++ and then return the pcm audio to Java. But I got all sort of weird looking data on the Java side. Also it was crashing half the time if not all the time with every change I made on the C++ code. I had similar issues when playing around with the vocoder on MD380 emulator. But that can just be me.
The speech from the microphone encoded through the vocoder cannot be reversed. The resulting speech is completely different. You will not get the same frames back.
Half rate is usually 72 bits with error correction bits. This vocoder expects input de-interleaved corrected in 49 bits form. So manually you will have to do the error correction your self, take a look at how OP25 does it.
I have yet to try full rate, or any encoding at all.
AMBE full rate also working at 88 bits, deinterleaved without error correction bits.
{(byte)88,(byte)-8,(byte)80,(byte)-107,(byte)-23,(byte)101,(byte)-128,(byte)45,(byte)78,(byte)-71,(byte)-58}, {(byte)88,(byte)-16,(byte)-21,(byte)54,(byte)-10,(byte)68,(byte)-128,(byte)1,(byte)-67,(byte)62,(byte)-21}, {(byte)108,(byte)-48,(byte)-49,(byte)-54,(byte)-66,(byte)-80,(byte)0,(byte)7,(byte)110,(byte)-17,(byte)120}, {(byte)84,(byte)-4,(byte)96,(byte)-125,(byte)106,(byte)64,(byte)0,(byte)37,(byte)13,(byte)21,(byte)-111}, {(byte)-116,(byte)-49,(byte)83,(byte)20,(byte)119,(byte)64,(byte)0,(byte)9,(byte)123,(byte)85,(byte)52}, {(byte)-128,(byte)-40,(byte)10,(byte)42,(byte)127,(byte)-113,(byte)-96,(byte)15,(byte)-97,(byte)36,(byte)55}, {(byte)-96,(byte)-24,(byte)-10,(byte)82,(byte)79,(byte)113,(byte)-128,(byte)0,(byte)-19,(byte)18,(byte)58}, {(byte)-128,(byte)-37,(byte)13,(byte)65,(byte)126,(byte)26,(byte)-128,(byte)11,(byte)-68,(byte)24,(byte)-121}, {(byte)112,(byte)-58,(byte)89,(byte)-99,(byte)-49,(byte)35,(byte)1,(byte)5,(byte)-127,(byte)-62,(byte)0}, {(byte)96,(byte)-100,(byte)-74,(byte)-56,(byte)-82,(byte)126,(byte)0,(byte)16,(byte)32,(byte)-77,(byte)-31}, {(byte)72,(byte)-36,(byte)7,(byte)-62,(byte)50,(byte)-6,(byte)4,(byte)67,(byte)-117,(byte)-66,(byte)-24}, {(byte)56,(byte)-27,(byte)-24,(byte)-124,(byte)88,(byte)123,(byte)-128,(byte)101,(byte)46,(byte)-47,(byte)-49}, {(byte)20,(byte)-28,(byte)-80,(byte)-42,(byte)108,(byte)-56,(byte)5,(byte)38,(byte)-67,(byte)70,(byte)90}, {(byte)88,(byte)-16,(byte)-50,(byte)-122,(byte)5,(byte)-111,(byte)1,(byte)38,(byte)-78,(byte)107,(byte)-79}, {(byte)116,(byte)-48,(byte)-61,(byte)42,(byte)-2,(byte)115,(byte)-128,(byte)9,(byte)-59,(byte)37,(byte)84}, {(byte)124,(byte)-40,(byte)-114,(byte)-30,(byte)-83,(byte)-25,(byte)-128,(byte)9,(byte)-98,(byte)1,(byte)-41}, {(byte)92,(byte)-47,(byte)40,(byte)-101,(byte)117,(byte)4,(byte)-96,(byte)40,(byte)25,(byte)-53,(byte)-74}, {(byte)-84,(byte)-4,(byte)59,(byte)44,(byte)28,(byte)-30,(byte)-127,(byte)9,(byte)59,(byte)11,(byte)113}, {(byte)52,(byte)-16,(byte)60,(byte)51,(byte)-96,(byte)-37,(byte)1,(byte)15,(byte)89,(byte)46,(byte)106}, {(byte)64,(byte)-35,(byte)4,(byte)-47,(byte)17,(byte)-71,(byte)0,(byte)-103,(byte)-68,(byte)27,(byte)73}, {(byte)36,(byte)-28,(byte)3,(byte)-12,(byte)121,(byte)17,(byte)3,(byte)-1,(byte)-54,(byte)-9,(byte)-74}, {(byte)60,(byte)-50,(byte)-56,(byte)-122,(byte)-62,(byte)79,(byte)0,(byte)-56,(byte)-47,(byte)-21,(byte)27}, {(byte)60,(byte)-47,(byte)-89,(byte)82,(byte)56,(byte)-64,(byte)0,(byte)-4,(byte)-12,(byte)-88,(byte)-94}, {(byte)40,(byte)-41,(byte)8,(byte)-2,(byte)-104,(byte)1,(byte)3,(byte)79,(byte)-44,(byte)-22,(byte)45}, {(byte)41,(byte)67,(byte)-36,(byte)7,(byte)15,(byte)60,(byte)0,(byte)-93,(byte)-18,(byte)97,(byte)-58}, {(byte)88,(byte)-8,(byte)-46,(byte)69,(byte)48,(byte)-93,(byte)0,(byte)62,(byte)105,(byte)-45,(byte)-97}, {(byte)-55,(byte)67,(byte)98,(byte)85,(byte)-44,(byte)-72,(byte)0,(byte)2,(byte)16,(byte)58,(byte)-76}, {(byte)-79,(byte)116,(byte)5,(byte)-43,(byte)53,(byte)83,(byte)101,(byte)-45,(byte)59,(byte)-119,(byte)73}, {(byte)-100,(byte)-65,(byte)4,(byte)-123,(byte)-72,(byte)70,(byte)-128,(byte)13,(byte)93,(byte)-89,(byte)40}, {(byte)116,(byte)-35,(byte)-62,(byte)98,(byte)54,(byte)40,(byte)-128,(byte)12,(byte)-86,(byte)21,(byte)-85}, {(byte)-76,(byte)-4,(byte)101,(byte)-67,(byte)9,(byte)-22,(byte)-128,(byte)15,(byte)63,(byte)-96,(byte)-122}, {(byte)-124,(byte)-68,(byte)-57,(byte)-16,(byte)-15,(byte)-26,(byte)-128,(byte)13,(byte)96,(byte)78,(byte)77}, {(byte)61,(byte)76,(byte)120,(byte)-94,(byte)75,(byte)77,(byte)0,(byte)57,(byte)-65,(byte)-84,(byte)-58}, {(byte)-119,(byte)60,(byte)68,(byte)-12,(byte)59,(byte)109,(byte)-51,(byte)-41,(byte)-19,(byte)94,(byte)65}, {(byte)-123,(byte)90,(byte)-116,(byte)-113,(byte)-66,(byte)6,(byte)-39,(byte)-43,(byte)57,(byte)-32,(byte)62}, {(byte)121,(byte)65,(byte)-68,(byte)-122,(byte)62,(byte)121,(byte)122,(byte)-24,(byte)115,(byte)-117,(byte)-125}, {(byte)105,(byte)46,(byte)44,(byte)126,(byte)88,(byte)76,(byte)0,(byte)40,(byte)77,(byte)-65,(byte)-60}, {(byte)97,(byte)103,(byte)-27,(byte)-127,(byte)-39,(byte)-96,(byte)-49,(byte)-36,(byte)84,(byte)-103,(byte)19}, {(byte)101,(byte)40,(byte)46,(byte)-19,(byte)92,(byte)55,(byte)-128,(byte)30,(byte)-64,(byte)-90,(byte)60}, {(byte)97,(byte)87,(byte)19,(byte)42,(byte)63,(byte)-89,(byte)37,(byte)16,(byte)50,(byte)-117,(byte)-15}, {(byte)97,(byte)-96,(byte)100,(byte)115,(byte)-26,(byte)127,(byte)0,(byte)27,(byte)72,(byte)109,(byte)10}, {(byte)50,(byte)57,(byte)47,(byte)20,(byte)29,(byte)-118,(byte)1,(byte)-56,(byte)-35,(byte)50,(byte)31}, {(byte)46,(byte)-50,(byte)-79,(byte)117,(byte)-57,(byte)-64,(byte)1,(byte)-69,(byte)70,(byte)-108,(byte)20}, {(byte)71,(byte)93,(byte)-60,(byte)-66,(byte)54,(byte)8,(byte)-128,(byte)84,(byte)-60,(byte)31,(byte)35}, {(byte)83,(byte)49,(byte)83,(byte)100,(byte)40,(byte)-116,(byte)-40,(byte)-64,(byte)-115,(byte)122,(byte)46}, {(byte)91,(byte)105,(byte)66,(byte)50,(byte)-12,(byte)93,(byte)-5,(byte)-83,(byte)51,(byte)-5,(byte)-103}, {(byte)91,(byte)120,(byte)-62,(byte)2,(byte)-31,(byte)-28,(byte)-1,(byte)-27,(byte)118,(byte)-57,(byte)-82}, {(byte)103,(byte)77,(byte)20,(byte)-94,(byte)105,(byte)59,(byte)-1,(byte)-92,(byte)-40,(byte)-108,(byte)-59}, {(byte)122,(byte)87,(byte)60,(byte)7,(byte)-30,(byte)67,(byte)-128,(byte)10,(byte)-103,(byte)107,(byte)100}, {(byte)94,(byte)46,(byte)-84,(byte)98,(byte)-110,(byte)-118,(byte)64,(byte)19,(byte)-95,(byte)-121,(byte)115}, {(byte)125,(byte)-66,(byte)-50,(byte)54,(byte)100,(byte)-110,(byte)0,(byte)14,(byte)-75,(byte)-93,(byte)36}, {(byte)-119,(byte)-72,(byte)-54,(byte)42,(byte)62,(byte)-21,(byte)0,(byte)10,(byte)30,(byte)-57,(byte)105}, {(byte)-123,(byte)-55,(byte)44,(byte)-109,(byte)-20,(byte)-111,(byte)78,(byte)34,(byte)-108,(byte)104,(byte)-70}, {(byte)125,(byte)80,(byte)-100,(byte)-90,(byte)-65,(byte)-6,(byte)0,(byte)-55,(byte)-51,(byte)-95,(byte)-97}, {(byte)-114,(byte)40,(byte)-124,(byte)-54,(byte)109,(byte)-45,(byte)40,(byte)-119,(byte)6,(byte)55,(byte)54}, {(byte)62,(byte)95,(byte)-16,(byte)19,(byte)50,(byte)123,(byte)0,(byte)56,(byte)120,(byte)7,(byte)-1}, {(byte)70,(byte)87,(byte)-14,(byte)-128,(byte)-62,(byte)-12,(byte)-112,(byte)3,(byte)4,(byte)-113,(byte)44}, {(byte)82,(byte)67,(byte)-56,(byte)-77,(byte)-112,(byte)-82,(byte)-128,(byte)116,(byte)-70,(byte)-26,(byte)57}, {(byte)86,(byte)-8,(byte)46,(byte)110,(byte)94,(byte)-24,(byte)-128,(byte)52,(byte)105,(byte)-77,(byte)12}, {(byte)90,(byte)63,(byte)-60,(byte)-76,(byte)31,(byte)1,(byte)-60,(byte)-89,(byte)-26,(byte)-20,(byte)63}, {(byte)98,(byte)73,(byte)37,(byte)-95,(byte)123,(byte)12,(byte)-6,(byte)48,(byte)-124,(byte)-66,(byte)-76}, {(byte)106,(byte)63,(byte)10,(byte)-89,(byte)-121,(byte)9,(byte)-120,(byte)12,(byte)105,(byte)5,(byte)-81}, {(byte)86,(byte)-73,(byte)51,(byte)-49,(byte)-110,(byte)72,(byte)-29,(byte)-90,(byte)50,(byte)6,(byte)-92}, {(byte)83,(byte)74,(byte)-16,(byte)49,(byte)-26,(byte)58,(byte)-2,(byte)64,(byte)92,(byte)-10,(byte)-89}, {(byte)87,(byte)69,(byte)-48,(byte)108,(byte)51,(byte)-38,(byte)-3,(byte)-54,(byte)104,(byte)-18,(byte)92}, {(byte)90,(byte)-16,(byte)-49,(byte)-50,(byte)-80,(byte)114,(byte)-6,(byte)-99,(byte)-93,(byte)92,(byte)-77}, {(byte)86,(byte)62,(byte)72,(byte)38,(byte)-82,(byte)-123,(byte)0,(byte)15,(byte)-85,(byte)-22,(byte)34}, {(byte)85,(byte)-12,(byte)51,(byte)-128,(byte)20,(byte)90,(byte)-128,(byte)62,(byte)-88,(byte)-7,(byte)-53}, {(byte)86,(byte)23,(byte)65,(byte)102,(byte)17,(byte)-12,(byte)-128,(byte)21,(byte)-25,(byte)-106,(byte)-78}, {(byte)86,(byte)3,(byte)-98,(byte)95,(byte)78,(byte)-50,(byte)0,(byte)54,(byte)-109,(byte)108,(byte)19}, {(byte)58,(byte)119,(byte)-81,(byte)-108,(byte)-107,(byte)-24,(byte)-128,(byte)-1,(byte)81,(byte)17,(byte)92}, {(byte)79,(byte)64,(byte)-77,(byte)118,(byte)-56,(byte)35,(byte)-9,(byte)-106,(byte)0,(byte)-91,(byte)-81}, {(byte)83,(byte)66,(byte)-15,(byte)121,(byte)13,(byte)68,(byte)-1,(byte)-112,(byte)39,(byte)-116,(byte)-2}, {(byte)83,(byte)78,(byte)-31,(byte)102,(byte)-54,(byte)63,(byte)-4,(byte)24,(byte)-96,(byte)-105,(byte)15}, {(byte)82,(byte)-38,(byte)105,(byte)-126,(byte)3,(byte)-73,(byte)-4,(byte)67,(byte)72,(byte)-12,(byte)-116}, {(byte)90,(byte)-16,(byte)-117,(byte)62,(byte)-28,(byte)92,(byte)-36,(byte)4,(byte)85,(byte)-69,(byte)29}, {(byte)85,(byte)-16,(byte)21,(byte)6,(byte)15,(byte)105,(byte)-128,(byte)57,(byte)120,(byte)-122,(byte)-102}, {(byte)89,(byte)-8,(byte)-124,(byte)12,(byte)10,(byte)-94,(byte)-124,(byte)62,(byte)99,(byte)-115,(byte)-91}, {(byte)89,(byte)-16,(byte)-23,(byte)32,(byte)-33,(byte)120,(byte)-128,(byte)3,(byte)-72,(byte)20,(byte)-86}, {(byte)85,(byte)85,(byte)122,(byte)-73,(byte)13,(byte)118,(byte)0,(byte)50,(byte)-74,(byte)6,(byte)-31}, {(byte)85,(byte)35,(byte)-76,(byte)94,(byte)-6,(byte)-35,(byte)-111,(byte)60,(byte)-61,(byte)-122,(byte)-52}, {(byte)81,(byte)-69,(byte)16,(byte)61,(byte)124,(byte)119,(byte)-58,(byte)42,(byte)118,(byte)9,(byte)87}, {(byte)85,(byte)-32,(byte)-12,(byte)-51,(byte)123,(byte)85,(byte)-16,(byte)82,(byte)-78,(byte)106,(byte)-44}, {(byte)89,(byte)113,(byte)-56,(byte)-121,(byte)-22,(byte)-66,(byte)-28,(byte)52,(byte)-59,(byte)-69,(byte)-125}, {(byte)85,(byte)42,(byte)-20,(byte)64,(byte)121,(byte)-44,(byte)0,(byte)22,(byte)-34,(byte)54,(byte)-82}, {(byte)81,(byte)59,(byte)25,(byte)-43,(byte)-13,(byte)-43,(byte)0,(byte)30,(byte)-54,(byte)0,(byte)-17}, {(byte)85,(byte)120,(byte)5,(byte)29,(byte)-92,(byte)-7,(byte)-128,(byte)28,(byte)115,(byte)-122,(byte)14}, {(byte)45,(byte)64,(byte)-34,(byte)-72,(byte)-57,(byte)-66,(byte)1,(byte)-47,(byte)-75,(byte)-108,(byte)-79}, {(byte)61,(byte)126,(byte)-84,(byte)18,(byte)24,(byte)-60,(byte)-128,(byte)-103,(byte)113,(byte)103,(byte)74}, {(byte)77,(byte)-64,(byte)-5,(byte)117,(byte)2,(byte)43,(byte)-79,(byte)16,(byte)40,(byte)69,(byte)119}, {(byte)81,(byte)87,(byte)116,(byte)110,(byte)77,(byte)14,(byte)-15,(byte)96,(byte)-74,(byte)75,(byte)-68}, {(byte)81,(byte)74,(byte)-23,(byte)66,(byte)74,(byte)-119,(byte)-8,(byte)114,(byte)-92,(byte)-36,(byte)-17}, {(byte)81,(byte)-38,(byte)40,(byte)-21,(byte)51,(byte)54,(byte)-8,(byte)6,(byte)-48,(byte)-11,(byte)-124}, {(byte)89,(byte)113,(byte)-115,(byte)94,(byte)45,(byte)58,(byte)-52,(byte)57,(byte)-73,(byte)112,(byte)-123}, {(byte)85,(byte)124,(byte)33,(byte)11,(byte)-107,(byte)22,(byte)-128,(byte)29,(byte)98,(byte)-85,(byte)-112}, {(byte)88,(byte)-31,(byte)-113,(byte)46,(byte)48,(byte)48,(byte)0,(byte)56,(byte)-93,(byte)3,(byte)105}, {(byte)80,(byte)-34,(byte)21,(byte)68,(byte)7,(byte)-112,(byte)-128,(byte)109,(byte)-110,(byte)85,(byte)-36}, {(byte)28,(byte)-20,(byte)14,(byte)74,(byte)-24,(byte)103,(byte)7,(byte)53,(byte)65,(byte)-71,(byte)33}, {(byte)124,(byte)-68,(byte)66,(byte)-29,(byte)-8,(byte)-17,(byte)0,(byte)12,(byte)29,(byte)108,(byte)20}, {(byte)80,(byte)-38,(byte)57,(byte)73,(byte)76,(byte)121,(byte)-128,(byte)-73,(byte)79,(byte)16,(byte)-35}, {(byte)41,(byte)94,(byte)-63,(byte)27,(byte)-63,(byte)48,(byte)-128,(byte)107,(byte)-20,(byte)-99,(byte)-92}, {(byte)48,(byte)-35,(byte)51,(byte)65,(byte)-92,(byte)-30,(byte)-127,(byte)-3,(byte)-14,(byte)-119,(byte)121}, {(byte)32,(byte)-12,(byte)48,(byte)87,(byte)69,(byte)-89,(byte)3,(byte)77,(byte)97,(byte)-51,(byte)-28}, {(byte)21,(byte)77,(byte)-59,(byte)-93,(byte)-40,(byte)-107,(byte)1,(byte)36,(byte)3,(byte)-87,(byte)3}, {(byte)40,(byte)-33,(byte)0,(byte)102,(byte)60,(byte)-30,(byte)3,(byte)61,(byte)-32,(byte)-117,(byte)12}, {(byte)64,(byte)-53,(byte)41,(byte)80,(byte)-93,(byte)32,(byte)0,(byte)-29,(byte)-118,(byte)-17,(byte)-15}, {(byte)64,(byte)-33,(byte)-64,(byte)-114,(byte)-93,(byte)-1,(byte)0,(byte)-46,(byte)38,(byte)65,(byte)50}, {(byte)77,(byte)80,(byte)123,(byte)-14,(byte)82,(byte)-101,(byte)-92,(byte)20,(byte)112,(byte)-68,(byte)55}, {(byte)84,(byte)-12,(byte)112,(byte)-63,(byte)-104,(byte)24,(byte)-64,(byte)50,(byte)42,(byte)32,(byte)80}, {(byte)80,(byte)-34,(byte)49,(byte)72,(byte)-50,(byte)89,(byte)-128,(byte)117,(byte)114,(byte)-125,(byte)-9}, {(byte)80,(byte)-36,(byte)34,(byte)-22,(byte)80,(byte)-75,(byte)-120,(byte)104,(byte)-69,(byte)-42,(byte)-118}, {(byte)89,(byte)-24,(byte)6,(byte)42,(byte)27,(byte)-65,(byte)-128,(byte)44,(byte)40,(byte)10,(byte)37}, {(byte)80,(byte)-34,(byte)45,(byte)-120,(byte)65,(byte)-5,(byte)0,(byte)126,(byte)-53,(byte)-25,(byte)-76}, {(byte)120,(byte)-40,(byte)-114,(byte)-66,(byte)21,(byte)-6,(byte)0,(byte)8,(byte)119,(byte)-70,(byte)-89}, {(byte)96,(byte)-98,(byte)-58,(byte)99,(byte)52,(byte)76,(byte)0,(byte)21,(byte)-76,(byte)-107,(byte)-8}, {(byte)92,(byte)-44,(byte)-109,(byte)-17,(byte)122,(byte)98,(byte)0,(byte)25,(byte)-51,(byte)-28,(byte)-119}, {(byte)-116,(byte)-37,(byte)20,(byte)101,(byte)-41,(byte)-16,(byte)0,(byte)9,(byte)102,(byte)86,(byte)-6}, {(byte)4,(byte)12,(byte)-3,(byte)123,(byte)-5,(byte)125,(byte)-14,(byte)123,(byte)37,(byte)-98,(byte)69}, {(byte)4,(byte)12,(byte)-3,(byte)123,(byte)-5,(byte)125,(byte)-14,(byte)123,(byte)37,(byte)-98,(byte)68}, {(byte)4,(byte)12,(byte)-3,(byte)123,(byte)-5,(byte)125,(byte)-14,(byte)123,(byte)61,(byte)-98,(byte)69}, {(byte)4,(byte)12,(byte)-3,(byte)123,(byte)-5,(byte)125,(byte)-14,(byte)123,(byte)61,(byte)-98,(byte)68}, {(byte)4,(byte)12,(byte)-3,(byte)123,(byte)-5,(byte)125,(byte)-14,(byte)123,(byte)37,(byte)-98,(byte)69}, {(byte)4,(byte)12,(byte)-3,(byte)123,(byte)-5,(byte)125,(byte)-14,(byte)123,(byte)61,(byte)-98,(byte)68}, {(byte)4,(byte)12,(byte)-3,(byte)123,(byte)-5,(byte)125,(byte)-14,(byte)123,(byte)37,(byte)-98,(byte)69}, {(byte)4,(byte)12,(byte)-3,(byte)123,(byte)-5,(byte)125,(byte)-14,(byte)123,(byte)61,(byte)-98,(byte)68}, {(byte)4,(byte)12,(byte)-3,(byte)123,(byte)-5,(byte)125,(byte)-14,(byte)123,(byte)37,(byte)-98,(byte)69}
Cool...