HADES-SA CODEC2 Audio Scrambled Structure

soundmodem, scrambling, codec2, ffmpeg, sox, grc road

[Common features of HADES-SA and HADES-L]

HADES-L does not use AX.25. Instead, it uses a proprietary "GENESIS format 800 bps FSK".
Looking at the source code for the HADES-L decoder released by AMSAT-EA, it is clear
that HADES-L also follows the same specifications mentioned above. Furthermore,
HADES-L's main.c directly includes genesis_crc.h and genesis_scrambler.h. In other words,
this is not merely a similarity in name, it confirms that the actual HADES-L decoder
employs the GENESIS method. HADES-L also employs the same GENESIS framing and scrambling
scheme and decoding formats as HADES-SA,
https://www.amsat-ea.org/proyectos/


HADES-SA
MSB-first
CRC-CCITT-FALSE
FSK GENESIS 800 bd
Initial value: 0x2C350000
Polynomial: x^17 + x^12 + 1
1600 Hz tone separation
Multiplicative scrambler

HADES-L
GENESIS CRC
GENESIS scrambler
Polynomial: x^17 + x^12 + 1
Scrambler initial value: 0x2C350000
CRC initial value: 0xFFFF

 
[HADES-SA + Soundmodem]

In 60923hda.wav, the received HADES-SA frames are displayed continuously
within UZ7HO's Soundmodem_for_HADES_SA_SpinnyONE.zip (v0.05b). The console window
of the bundled KISSGENESIS.exe which interfaces with Soundmodem displays items such
as packet type 13 and packet type 11 (CODEC2 voice) from the SpinnyONE HADES-SA.
This 60923hda.wav is an actual HADES-SA audio file that can be successfully decoded
as GENESIS 800-baud FSK.

HADES-SA, 60923hda.wav
#14185673, 2026-05-30 07:06:13
FSK 800 bps, 1600 Hz separation
Measured value Low:620 Hz, High:2220 Hz

Ref.SDM: E-Mail from UZ7HO, 11 Oct 2026
hs_soundmodem31.zip for GFSK_Satellites
erminaz.zip for ERMINAZ
hadesl.zip  for HADES-L
unne1b.zip  for UNNE-1B
lilac2.zip  for ASRTU-1/LILACSAT2/BY70/JAMX01
            LILACSAT2 uses FL114 mode, other sats FL223





 
 HADES-SA CODEC2 Scrambled Structure 


[Question about differences between SoundModem and KISSGENESIS output]

From: Andrei, UZ7HO
Date: 29 Oct 2026

Hello, Mineo.

CODEC2 (type 11) are raw frames, there isn’t even a checksum check
and Soundmodem receives them in their original form. Since they lack
a checksum, these frames are received only by the main demodulator.
 
KISSGENESIS has "hadessa.dll" which contains some functions for
the post-processing of these frames. The different data is the result
of unscrambling.

You can find a source code there:

https://github.com/AMSAT-EA/HADES-SA_SpinnyONE/tree/main/byte_version

Look for "visualiza_codec2" etc.

On Thursday, October 29, 2026, 1:17:48 you wrote:

> Hello Andrei, UZ7HO
> 
> I am currently working on decoding HADES-SA packets using SoundModem and KISSGENESIS.
> 
> I noticed that the output data from SoundModem and KISSGENESIS appear to be different,
> even though the two programs work together and the data seems to
> correspond to the same frame and time.
> Source Audio is 60923hda.wav.
> For example, at approximately 22:45:00 on October 28, 2026,
> SoundModem displayed the following frame:
> 
> ------------------------------------------------------
> 
> soundmodem.exe for HADES-SA:
> 
> [frm_type:11 len:37]
> B3 00 23 8A 55 29 A8 88 E9 A7 64 C3 91 6C 96 28
> EB 3A 1E 87 6A 7E BD A9 C3 DD 72 2C 5F CA 9E CE
> 99 A6 14 BC 0D
> 
> At approximately the same time, KISSGENESIS.exe displayed:
> 
> frame num : 0
> data :
> CE 9F 80 10 29 CF 80 90 5A 89 40 00 1B 73 C0 60
> CE EC 40 00 62 BF 80 00 CE BA 80 00 28 D4 C0 40
> CE C2 80 60 CE FF 80 00
> 
> ------------------------------------------------------
> 
> Could you please explain why these two outputs look different?
> 
> Are these two data sequences representations of the same frame,
> with some conversion or processing performed by KISSGENESIS?
> 
> If so, could you briefly explain the conversion process or point me
> to the relevant documentation or source code?
> 
> I have attached the log containing the output from both programs for reference.
> 
> Thank you very much for your help.
> 
> Best regards. JE9PEL, Mineo Wakita


[Follow-up: CODEC2 type 11 descrambling in KISSGENESIS]

From: Andrei, UZ7HO
Date: 29 Oct 2026

Hello, Mineo.

It's a bit of a complicated process.

Let's look at the structure of the "Type=11" frame:

B3 00 23 8A 55 29 A8 88 E9 A7 64 C3 91 6C 96 28 EB 3A 1E 87 6A 7E BD A9 C3 DD 72 2C 5F CA 9E CE 99 A6 14 BC 0D

"B3" contains SAT_ID=03 and PKT_TYPE=0B

"00" is serial number of CODEC2 packet.

Each packet contains 10 CODEC2 timeslots of 28 bits each, that gives us a total of 35 bytes (the rest part).

These 35 bytes are scrambled using the following XOR sequence:

  uint8_t xor_codec2[35] = {
                             0xed, 0x15, 0xd5, 0x3b, 0x34, 0x70, 0xe0, 0xfd, 0xed, 0x83, 0x90, 0xdb,
                             0xaa, 0x2e, 0x25, 0xd6, 0x5e, 0x81, 0x41, 0x86, 0xbd, 0x67, 0x79, 0x5d,
                             0x70, 0xa1, 0x13, 0xce, 0x50, 0x0c, 0x19, 0xca, 0xfb, 0x44, 0x0d };

Since 28 bits are not a multiple of 8 bits, we need to align them to 32 bits sequence using padding bits.

Let's take first timeslot: "23 8A 55 2"

  23 XOR ED = CE
  8A XOR 15 = 9F
  55 XOR D5 = 80
  2 XOR 3 = 1

So we have the sequence "CE 9F 80 1", adding 4 padding bits to get a 32 bits word: "CE 9F 80 10".

In this way we perform all 10 iterations, which give us 40 bytes that you can see in KISSGENESIS output.


On Thursday, October 29, 2026, 9:08:35 you wrote:

> Hello Andrei,
> 
> Thank you very much for your quick and helpful explanation.
> I would like to clarify two details about the descrambling of CODEC2 type 11 frames.
> 
> 1. In the 37 byte SoundModem frame, which bytes are descrambled?
>    Is the 3 byte header (B3 00 23) excluded, with descrambling
>    applied only to the remaining payload?
> 2. Could you explain how the following SoundModem frame is
>    transformed into the data displayed by KISSGENESIS?

> SoundModem input:
> B3 00 23 8A 55 29 A8 88 E9 A7 64 C3 91 6C 96 28
> EB 3A 1E 87 6A 7E BD A9 C3 DD 72 2C 5F CA 9E CE
> 99 A6 14 BC 0D
> 
> KISSGENESIS output:
> CE 9F 80 10 29 CF 80 90 5A 89 40 00 1B 73 C0 60
> CE EC 40 00 62 BF 80 00 CE BA 80 00 28 D4 C0 40
> CE C2 80 60 CE FF 80 00
> 
> If possible, could you point me to the specific function in the
> source code that performs this conversion,
> or provide a brief explanation of the algorithm?
> 
> This will help me implement and verify the same processing in my GNU Radio HADES-SA decoder.
> 
> Thank you again for your assistance.
> 
> Best regards,
> 
> JE9PEL, Mineo Wakita
--
Best regards, Andy


[37 bytes frame structure of SoundModem]




[Actually convert the first 28 bits]

  Item                     Value
  28 bits input            23 8A 55 2
  Start of XOR sequence    ED 15 D5 3
  After XOR                CE 9F 80 1
  32 bits aligned output   CE 9F 80 10

XOR is an operation that yields 0 when the bits are the same, and 1 when the bits are different.
Viewed at the byte level, for example, it works as follows:

  23 XOR ED = CE
  8A XOR 15 = 9F
  55 XOR D5 = 80

Finally, only 4 bits are processed, and the remaining 4 bits are added as padding for alignment.
As a result, a 28 bits input becomes a 32-bits output.


[Basic principles of XOR]

  A     B     A XOR B
 ---   ---   ---------
  0     0        0
  0     1        1
  1     0        1
  1     1        0

  Hex  Binary
  23   0010 0011
  ED   1110 1101

       0 0 1 0   0 0 1 1   ... 23
  XOR  1 1 1 0   1 1 0 1   ... ED
       -----------------
       1 1 0 0   1 1 1 0   ... CE

Then,  1100 1110  ... CE

In this instance of HADES-SA, this operation is applied to each bit,
for example, 23 XOR ED = CE.

The useful property of XOR is that applying it again with the same value restores the original
state,ie, descrambling: (A XOR B) XOR B = A. This is the fundamental principle by which data
can be descrambled using the fixed XOR sequence in this instance.


[About the XOR sequence]

xor_codec2[35] is a fixed 35 bytes XOR sequence used to descramble CODEC2 data. Its 280 bits
are aligned MSB-first with the 280 bits received payload and processed in ten 28 bit slots.
Each value in the array is written in hexadecimal. A simple periodic pattern or an obvious
mathematical rule cannot be assumed from the values alone. The generation method and any
underlying mathematical pattern have not yet been verified; therefore, the array is treated
here as a fixed sequence specified by the published source code.


[Why does it go from 37 bytes to 40 bytes?]

35 bytes is 280 bits, so,

  280 bits / 28 bits = 10 slots
  10 slots x 32 bits = 320 bits
  320 bits / 8 = 40 bytes

Then, 40 bytes output of KISSGENESIS is the result of aligning ten 28 bits slots into 32 bits
segments. 37 bytes frame and 40 bytes output do not match in length because their formats differ.


[Application to GNU Radio experiments]

 1. Remove "B3 00" from the frames received via SoundModem and extract the remaining 35 bytes.
 2. Using the 35 bytes XOR sequence provided by UZ7HO, descramble the data in 28 bit segments.
 3. Align each slot into 32 bit blocks to generate 40 bytes output.
 4. Compare this with the output from KISSGENESIS to verify that all 10 slots match.


[Verification of the SoundModem 37 bytes to KISSGENESIS 40 bytes conversion]

Based on UZ7HO's explanation, the 37 bytes CODEC2 frame (PKT_TYPE = 0B) output by SoundModem
was processed to recover ten 28 bit slots and generate 40 bytes.


[Conversion procedure]

Remove the first two bytes (B3 00) and treat the remaining 35 bytes as a 280 bit stream.
Treat the published 35 bytes fixed XOR array as another 280 bit stream. Using MSB-first bit
order, XOR the two streams in ten consecutive 28 bit slots. Append four 0000 padding bits
to each 28 bit result, aligning each slot to four bytes.


[Calculated output]

  CE 9F 80 10 29 CF 80 90
  5A 89 40 00 1B 73 C0 60
  CE EC 40 00 62 BF 80 00
  CE BA 80 00 28 D4 C0 40
  CE C2 80 60 CE FF 80 00

All 40 bytes matched the recorded KISSGENESIS output for the same frame.


[Conclusion]

The conversion from the SoundModem raw frame to the KISSGENESIS 40 bytes output was reproduced
successfully for this sample frame. Further work should test additional frames and establish
how the converted data is passed to the CODEC2 audio-processing stage.

 
[HADES-SA CODEC2 Audio Reconstruction Successful] (29-30 Oct 2026)

I successfully conducted an experiment to reconstruct audio from HADES-SA CODEC2 (type 11) frames
received using SoundModem.exe and KISSGENESIS.exe. Analyzing the scrambling structure of
the received data proved extremely challenging. With advice from UZ7HO, it took more than
a month from the start of this experiment to finally achieve the audio reconstruction.
The procedure is described below.

  


The "HADES-SA SpinnyONE CODEC2 utilities" published by AMSAT-EA were used.
The version dated April 3, which I initially downloaded, produced an error when running
c2dec.exe, stating that "libgcc_s_seh-1.dll" could not be found. I therefore downloaded
the April 4 version again from the AMSAT-EA project page. This version included the missing
DLL, and I confirmed that c2dec.exe started normally. AMSAT-EA Projects


[Preparing the CODEC2 Frame Files]

A new sat folder was created inside the utility folder to store the multiple CODEC2 frame
files (.bin) received by KISSGENESIS. Each .bin file was saved manually in this folder.

The run_codec2.bat file was also modified to read the CODEC2 frame files from the sat folder
so that they could be merged. The working BAT file can be downloaded here: run_codec2.bat

(Modified line) (for %%F in (sat\*codec2_frame_*.bin) do echo %%F) > codec2_file_list.txt

(BAT Execution) C:\Program Files\hadesa\AMSAT-EA_HADES-SA_SpinnyONE_CODEC2_utilities>run_codec2.bat


[Merging the CODEC2 Frame Files]

The run_codec2.bat batch file was executed from the command line. It automatically launched
codec2-merge-windows-x86.exe using the following command:

  codec2-merge-windows-x86 codec2_file_list.txt hades_sa.c2

The 25 available CODEC2 frame files listed in codec2_file_list.txt were merged into hades_sa.c2.
The 12 missing frames (frames 004–015) were filled with zero data, and the process completed
successfully. The batch file then automatically ran c2dec to convert hades_sa.c2 into hades_sa.raw,
followed by FFmpeg to generate the audio file hades_sa.wav. No manual command-line execution of
codec2-merge-windows-x86.exe was required, it was launched automatically by run_codec2.bat.


[Decoding with c2dec.exe]

The hades_sa.c2 file was copied to the utility folder, and the following command was
executed from the Windows Command Prompt:

  c2dec 700C hades_sa.c2 hades_sa.raw

The 700C option specifies the CODEC2 700 bit/s speech coding mode.
Execution result: Detected Codec2 file version 1.2 in mode 8
The hades_sa.raw file was generated without errors.

 
[Converting to WAV with FFmpeg]

The RAW audio data was then converted to a WAV file.

  ffmpeg\bin\ffmpeg -f s16le -ar 8000 -ac 1 -i hades_sa.raw hades_sa.wav

Generated WAV file:

  File: hades_sa.wav
  Format: PCM signed 16 bits
  Sampling rate: 8000 Hz
  Channel: Mono
  Duration: 14.80 seconds


[Finally, I Heard the Audio!]

When the generated hades_sa.wav file was played on Windows, I was finally able to hear human speech.

  
    61030cd2.wav (hades_sa.wav)


I successfully merged the CODEC2 frames from the received HADES-SA data, decoded them, converted
the decoded audio to WAV format, and played back the speech.

In this experiment, 12 of the 37 frames were missing, and those portions were filled with zero data.
Therefore, the audio is not complete. Nevertheless, successfully recovering human speech from the
received digital data is a significant achievement.

 
[Additional Test: Converting the RAW Audio with SoX]

Following a suggestion from UZ7HO, I tried using SoX instead of FFmpeg to convert the CODEC2 RAW
audio file into WAV format.

From: Andrei, UZ7HO
Date: 1 Nov 2026

By the way, I used SoX instead of FFMPEG for RAW to WAV converting:

  sox -t raw -b 16 -e signed-integer -r 8000 -c 1 -L hades_sa.raw hades_sa.wav

It takes less space on disk.

> On Sunday, November 1, 2026, 9:46:47 you wrote:
> 
> Hello Andy.
> 
> HADES-SA CODEC2 Audio Playback Successful.
> https://www.asahi-net.or.jp/~ei7m-wkt/numb1201.htm
> https://www.ne.jp/asahi/hamradio/je9pel/hadeslgr.htm
> 
> Thank you.
> JE9PEL, Mineo Wakita
--
Best regards, Andy


The conversion was performed with SoX v14.4.2 using the following command:

  sox -t raw -b 16 -e signed-integer -r 8000 -c 1 -L hades_sa.raw hades_sa.wav

The resulting hades_sa.wav was created successfully in the working folder. Its file size
was a few dozen bytes smaller than the WAV file previously generated with FFmpeg. I played
the new SoX-generated WAV and compared it by ear with the FFmpeg version. Both sounded the
same, with clear human voice audio. I could not hear any noticeable difference. This test
confirmed that SoX can also be used successfully for the RAW-to-WAV conversion in this
HADES-SA CODEC2 audio workflow.  61101cd2.wav (hades_sa.wav)

Note: The comparison was made by listening; the audio data was not compared digitally.
      SoX site: https://sourceforge.net/projects/sox/files/?utm_source=chatgpt.com

 
[Future GNU Radio Companion (GRC) Experiments]

In this experiment, audio playback was confirmed through manual processing using the CODEC2 utilities.
The next step is to complete the automated reception, synchronization, and frame extraction process
in GNU Radio Companion (GRC), and connect it to the CODEC2 audio processing demonstrated here.
The ultimate goal is to achieve audio playback from received data not only from HADES-SA, but also
from HADES-L, which uses the same GENESIS format.


[HADES-SA + GRC] (In Progress, 9 Nov 2026)

Experiments on receiving and decoding HADES-SA using GNU Radio Companion (GRC) are still in progress.
In this experiment, I confirmed that human speech could be played back from the received data using
the CODEC2 utilities. The next step is to incorporate this processing into the GRC flowgraph, with
the goal of automating the entire process from reception to audio playback.




https://www.ne.jp/asahi/hamradio/je9pel/HADES_SA_800bps_FSK_WAV_CHECK27.grc (in progress)



Back to Top
Back to Home Page