HADES-SA CODEC2 音声スクランブル構造


● (No.1201) HADES-SA CODEC2 音声スクランブル構造 (2026年10月13日)
 ----------------------------------------------------------------

[HADES-SA と HADES-L の共通点]

HADES-L は AX.25 ではなく、独自の "GENESIS形式 800 bps FSK" である。
AMSAT-EA が公開している HADES-L のデコーダーのソースコードを見ると、
HADES-L でも明確に、上記と同じ仕様である。さらに、HADES-L の main.c
は、genesis_crc.h と genesis_scrambler.h を直接インクルードしている。
つまり、これは単なる名称の類似ではなく、実際の HADES-Lデコーダーが
GENESIS方式を使っていることが確認できる。HADES-Lは、HADES-SAと同じ
GENESISフレーミング、スクランブル方式とデコード形式を採用している。
https://www.amsat-ea.org/proyectos/


HADES-SA
MSB-first
CRC-CCITT-FALSE
FSK GENESIS 800 bd
初期値: 0x2C350000
多項式: x^17 + x^12 + 1
1600 Hz tone separation
Multiplicative scrambler

HADES-L
GENESIS CRC
GENESIS scrambler
多項式: x^17 + x^12 + 1
Scrambler初期値: 0x2C350000
CRC初期値: 0xFFFF


[HADES-SA + Soundmodem]

60923hda.wav は、UZ7HO Soundmodem_for_HADES_SA_SpinnyONE.zip v0.05b 上に
HADES-SA の受信フレームが連続表示されていく。Soundmodem に連携する同梱の
KISSGENESIS.exe の Console画面には、SpinnyONE HADES-SA の packet type 13
packet type 11 (CODEC2 voice) などが表示されている。この 60923hda.wav は
GENESIS 800 baud FSK として正常にデコードできる実際のHADES-SA音源である。

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

参考SDM: E-Mail from UZ7HO, 11 Oct 2026
hs_soundmodem31.zip GFSK一般衛星用
erminaz.zip ERMINAZ衛星用
hadesl.zip  HADES-L衛星用
unne1b.zip  UNNE-1B衛星用
lilac2.zip  ASRTU-1/LILACSAT2/BY70/JAMX01衛星用
            LILACSAT2 uses FL114 mode, other sats FL223





 
 HADES-SA CODEC2 スクランブル構造 


[SoundModem と KISSGENESIS の出力の差異に関する質問]

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


[続き: KISSGENESIS における CODEC2タイプ11デスクランブル]

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


[SoundModem の37バイトのフレーム構造]




[最初の28ビットを実際に変換する]

  項目                    値
  入力28ビット            23 8A 55 2
  XOR系列の先頭           ED 15 D5 3
  XOR後                   CE 9F 80 1
  32ビットに整列した出力  CE 9F 80 10

XORは、同じビット同士なら 0、異なるビット同士なら 1 になる演算である。
バイト単位で見ると、たとえば次のようになる。

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

最後は4ビットだけ処理し、残りの4ビットを整列用のパディングとして加える。
そのため、28ビットの入力が 32ビットの出力になる。


[XOR の基本原理]

XOR は “eXclusive OR” の略で、日本語では「排他的論理和(はいたてきろんりわ)」という。
  OR:どちらか一方、または両方が 1 なら 1
  Exclusive OR (XOR):どちらか一方だけが 1 なら 1, 両方同じなら 0

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

「Exclusive」は「排他的な、どちらか一方だけ」という意味である。

まず16進数を2進数に変換する。

       16進数   2進数
       23       0010 0011
       ED       1110 1101

次に、1ビットずつ XOR 演算する。

       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

結果を16進数に戻す。

  1100 1110  ← CE

計算結果: 23 XOR ED = CE

今回の HADES-SA の例では、23 XOR ED = CE のように、各ビットにこの演算を適用している。
便利なのは、XOR は同じ値をもう一度 XOR すると元に戻る(解除)という性質である。

  (A XOR B) XOR B = A

これが、今回の固定XOR系列を使ってデータをスクランブル解除できる基本原理である。


[XOR sequence (固定XOR系列) について]

xor_codec2[35] は、CODEC2データのスクランブル解除に使用する35バイトの固定XOR系列である。
受信データの280ビットと、この系列の280ビットを MSB-first で対応させて、28ビット単位の
10スロットに分けてXOR演算を行う。この配列の各数値は16進数で表されている。数値の並びに
単純な周期性や、直ちに判別できる規則性があるとは限らない。現時点では、配列の生成方法や
数値列の数学的な規則性は確認できていない。ここでは、公開ソースコードに示された固定系列
として扱う。


[なぜ37バイトから40バイトになるのか]

35バイトは280ビットである。

  280ビット  ÷ 28ビット = 10スロット
  10スロット × 32ビット = 320ビット
  320ビット ÷ 8 = 40バイト

つまり、KISSGENESISの40バイト出力は、10個の28ビットスロットをそれぞれ32ビットに整列させ
た結果である。37バイトのフレームと40バイトの出力は、形式が異なるため、長さは一致しない。


[GNU Radio実験への応用]

  1. SoundModemで受信したフレームから B3 00 を除き、残り35バイトを取り出す。
  2. UZ7HO局が示した35バイトの XOR系列を使い、28ビットずつデスクランブルする。
  3. 各スロットを32ビットに整列し、40バイトの出力を生成する。
  4. KISSGENESISの出力と比較し、全10スロットが一致するか確認する。


[SoundModem 37バイトから KISSGENESIS 40バイトへの変換検証]

UZ7HO局の説明に基づき、SoundModemが出力したCODEC2 (PKT_TYPE = 0B) の37バイトフレームから、
10個の28ビットスロットを復号し、40バイトのデータを計算した。


[変換方法]

先頭2バイト (B3 00) を除いた35バイトを280ビットの系列として扱う。
公開された固定XOR配列35バイトを同じく280ビットの系列として扱い、MSB-firstで28ビットずつ、
10スロットに分割してXORする。各28ビットスロットの末尾に4ビットの0000を追加し、4バイトに整列する。


[計算結果]

  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

この40バイトは、記録されていたKISSGENESISの同一フレームの出力と、全バイトで一致した。


[結論]

このサンプルフレームについて、SoundModemの生フレームからKISSGENESISの40バイト出力への変換を再現できた。
今後は、複数フレームでの再現性と、変換後のデータがCODEC2音声処理にどのように渡されるかを確認する。


[HADES-SA CODEC2 音声復元成功] (29-30 Oct 2026)

SoundModem.exe と KISSGENESIS.exe によって取得した HADES-SA の CODEC2(type 11)フレームから、実際に
音声を復元する実験に成功した。取得データのスクランブル構造の解析が大変難儀で、UZ7HO局の助言により、
この実験に取り組み始めて一ヶ月以上掛かって、ようやく音声の復元に成功した。以下にその手順を示す。

  


AMSAT-EA が公開している "HADES-SA SpinnyONE CODEC2 utilities" を使用する。
最初に入手していた4月3日版では、c2dec.exe の実行時に "libgcc_s_seh-1.dll" が見つからないという
エラーが発生した。そこで、AMSAT-EA の公開ページから4月4日版を再ダウンロードした。この版には不足
していた DLL が含まれており、c2dec.exe が正常に起動することを確認した。 AMSAT-EA Projects


[CODEC2 frameファイルの確認]

KISSGENESIS によって生成された CODEC2 frameファイル(.bin)は、satフォルダに保存されている。
各ファイルは 40バイトである。今回確認できたファイルは、全37フレーム中25フレームであった。
フレーム番号004~015 の12フレームは欠落していた。


[CODEC2 frameファイルの準備]

また、これらのファイルを結合するため、run_codec2.bat を修正し、satフォルダ内の CODEC2 frameファイル
を読み込むようにした。この修正済みのBATファイルは、ここからダウンロードできる。→ run_codec2.bat

(修正行) (for %%F in (sat\*codec2_frame_*.bin) do echo %%F) > codec2_file_list.txt

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


[CODEC2ファイルの結合]

run_codec2.bat をコマンドラインから実行する。BATファイル内の処理により codec2-merge-windows-x86.exe
が自動起動され、codec2_file_list.txt に記載された25個の CODEC2 frameファイルが結合される。つまり、

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

hades_sa.c2 が自動生成される。続いて c2dec と ffmpeg が自動実行され、hades_sa.wav まで生成された。
欠落していた12フレームはゼロデータで補われ、正常終了した。


[c2dec.exe によるデコード]

utilityフォルダに hades_sa.c2 をコピーし、Windowsコマンドプロンプトから次のコマンドを実行した。

  c2dec 700C hades_sa.c2 hades_sa.raw

700C は、CODEC2の 700 bit/s系の音声符号化モードを指定するものである。
実行結果: Detected Codec2 file version 1.2 in mode 8
エラーなく hades_sa.raw が生成された。


[FFmpeg による WAV変換]

続いて、RAW音声データを WAVファイルに変換した。

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

生成された WAVファイル:

  ファイル名: hades_sa.wav
  形式: PCM signed 16 bits
  サンプルレート: 8000 Hz
  チャンネル: Mono
  長さ: 14.80 seconds


[ついに音声を確認!]

生成された hades_sa.wav を Windows 上で再生したところ、ついに人の音声を聞くことができた。

  
    61030cd2.wav (hades_sa.wav)


HADES-SA の受信データから CODEC2 フレームを結合し、デコード・音声WAV変換を経て、実際に音声を
再生することに成功した。今回は、37フレーム中12フレームが欠落しており、その部分はゼロデータで
補われているため、完全な音声ではない。しかし、受信したデジタルデータから人の音声を取り出せた
ことは、大きな成果である。


[追加実験: SoXによるRAW音声のWAV変換]

UZ7HO局から、FFmpegの代わりに SoX を使用して RAW音声をWAVに変換する別の方法のメールがあった。

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


そこで、Windows環境に SoX v14.4.2 を導入し、次のコマンドで変換を実行した。

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

変換は正常に完了し、作業フォルダー内に新しい hades_sa.wav が生成された。このファイルサイズは
以前 FFmpeg で作成した hades_sa_ffmpeg.wav より数十バイト小さくなった。新しい SoX版WAVを再生
し、FFmpeg版と耳で聞き比べると、どちらも人の音声が明瞭に再生され、聞き取れる違いはなかった。
今回の実験により、HADES-SA CODEC2音声の RAWからWAVへの変換に、SoXも問題なく使用できることを
確認した。

※比較は聴感によるもので、音声データのデジタル比較は行っていない。
 SoXサイト: https://sourceforge.net/projects/sox/files/?utm_source=chatgpt.com


[今後の GNU Radio Companion (GRC)実験]

今回の実験では、CODEC2 utility を使用した手動処理によって、音声再生まで確認できた。今後は、
GNU Radio Companion (GRC) による受信・同期・フレーム抽出の自動処理を完成させ、今回確認した 
CODEC2 音声処理につなげていく。最終目標は、HADES-SA だけでなく、同じ GENESIS形式を使用する
HADES-L についても、受信から音声再生までを実現することである。


[HADES-SA + GRC] (開発途中, 30 Oct 2026)

GNU Radio Companion (GRC) による HADES-SA の受信・デコード実験は、現在も継続中である。
今回、CODEC2 utility を使用して、受信データから人の音声を再生するところまで確認できた。
今後は、この処理を GRC のフローグラフに組み込み、受信から音声再生までの一連の自動処理を目指す。




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



トップ へ戻る.
前のページ へ戻る.
次のページ へ移る.(編集中)
ホームページ(目次) へ戻る.