{"id":13492230,"url":"https://github.com/nyatla/TBSKmodem","last_synced_at":"2025-03-28T09:34:04.497Z","repository":{"id":65682124,"uuid":"543994656","full_name":"nyatla/TBSKmodem","owner":"nyatla","description":"TBSK (Trait Block Shift Keying) audio modem Communication Library for Python","archived":false,"fork":false,"pushed_at":"2024-03-26T04:23:07.000Z","size":1550,"stargazers_count":10,"open_issues_count":10,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-05-02T01:55:19.403Z","etag":null,"topics":["audio","modem","python","sound","wireless-communication"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nyatla.png","metadata":{"files":{"readme":"README.ja.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-01T11:03:55.000Z","updated_at":"2024-07-31T21:51:31.939Z","dependencies_parsed_at":"2024-02-24T23:29:06.765Z","dependency_job_id":"d43678e7-e572-4cee-9913-e1438cd88fce","html_url":"https://github.com/nyatla/TBSKmodem","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nyatla%2FTBSKmodem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nyatla%2FTBSKmodem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nyatla%2FTBSKmodem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nyatla%2FTBSKmodem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nyatla","download_url":"https://codeload.github.com/nyatla/TBSKmodem/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246004338,"owners_count":20708192,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio","modem","python","sound","wireless-communication"],"created_at":"2024-07-31T19:01:04.213Z","updated_at":"2025-03-28T09:34:04.078Z","avatar_url":"https://github.com/nyatla.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# TBSK modem\n\nEnglish document 👉[README.md](README.md)\n\nTBSK (Trait Block Shift Keying) modemは、FFT/IFTTを使わない、低速、短距離の音響通信の実装です。\nバイト/ビットストリームの振幅信号への変調、振幅信号からバイト/ビットストリームへの復調ができます。\n\nPythonプラットフォーム向けには、開発用のライブラリとコンソールアプリ[tbskmodem](tbskmodem.md)があります。\n\n![preview_tbsk](https://user-images.githubusercontent.com/2483108/194768184-cecddff0-1fa4-4df8-af3f-f16ed4ef1718.gif)\n\n[Youtube](https://www.youtube.com/watch?v=4cB3hWATDUQ)でみる（信号音付きです。）\n\n## 対応プラットフォーム\n\nPythonプラットフォーム以外にも、メジャーな言語向けの実装があります。\n\n- TBSKmodem for Python\n- [TBSKmodem for C#](https://github.com/nyatla/TBSKmodemCS)\n- [TBSKmodem for C++](https://github.com/nyatla/TBSKmodemCpp)\n- [TBSKmodem for JavaScript](https://github.com/nyatla/TBSKmodemJS)\n- [TBSKmodem for Java](https://github.com/nyatla/TBSKmodemJava)\n- [TBSKmodem for Processing](https://github.com/nyatla/TBSKmodem-for-Processing)\n- [TBSKmodem for MicroChip](https://github.com/nyatla/TBSKmodemMicro)\n\n\n## 性能\n\n静かな室内での音響通信性能は、ビットレートが5bps～1kbps、通信距離は1mくらいです。\nパソコンに備わるマイクとスピーカーで通信ができます。\n\nその他の媒体でも、それなりに波形を伝送できれば通信できると思います。\n\n\n## 仕様\n\n| パラメータ | 値 |\n| --- | --- |\n| 変調方式 | 特徴ブロック差動変調 |\n| ビットレート | 5～1kbps |\n| 搬送波周波数 | 任意 |\n| 帯域幅 | 5Hz～全帯域 |\n| エラー訂正/検出 | なし |\n\n変調方式の詳細はこちら format: [TBSKmodem.pdf](./doc/TBSKmodem.pdf)\n\n### 特徴ブロック差動変調\n\nTBSKの特徴ブロック差動変調は、波形シンボルの代わりに任意形状のトーン信号とその反転値を、2値の伝送シンボルとして使います。\nトーン信号はスペクトラム拡散したSin波を使いますが、他にも任意形状の波形を使うことができます。\n復調は、隣接するシンボルの相関値を遅延検波します。相関値は1,-1を取るので、これをビットに復調します。\n\nこの伝送方式のパラメータは、トーン信号長(Tick数×搬送波周波数)のみです。トーン信号長だけ適合していれば、同一な復調器で信号の形式によらず復調することができます。\n\n### 信号同期\n\n信号の検出は相関値を一定時間観測して判定します。信号の先端には通常のシンボルよりも長い同期パターンを配置します。\n初期の同期シンボル検知のほか、同期ずれを補正するためにシンボル反転時の相関ピークを検出します。\n搬送波の安定しないシステムでシンボル1の信号を長時間を送ると、同期が取れずにストリームが中断します。\n長時間の通信では、数十秒に一度は0のシンボルを連続して送信されるようにデータを加工してください。\n\n### トーン信号\n\n標準のトーン信号は、Sin波をPN符号で位相シフトしたスペクトラム拡散波形です。\nトーン信号は復調側でS/N比が高くなる形状であれば何でも構いません。トーン信号にサイン波を使用すると、DPSK変調と同じ動作をします。\n\n### 外乱耐性\n\nトーン信号が長いほど外乱耐性は強くなりますが、トーン信号が長くなるほどビットレートは低下します。\n搬送波周波数に対する最大通信レートの理論値は1bit/Hzです。実際には0.01bit/Hzが目安となります。\n\nトーン信号は、線路媒体の特性に合わせて、時間方向、周波数方向に拡散できます。\n\n\n### パケット仕様\n現状のプロトコルは、開始点検出とそれに続くペイロード読出しのみを実装しています。パケットサイズや終端識別子、エラー訂正、検出についてはアプリケーションで実装してください。\n\n## ライセンス\n\n本ソフトウェアは、MITライセンスで提供します。ホビー・研究用途では、MITライセンスに従って適切に運用してください。\n産業用途では、特許の取り扱いに注意してください。\n\nこのライブラリはMITライセンスのオープンソースソフトウェアですが、特許フリーではありません。\n\n特許権については、YAMAHA CORPORATION様の所有する以下の特許、及び派生元特許周辺に類似する箇所がある様に思われます。\n専門家の監修は受けておりませんので、詳細はご自身でお調べください。\n\n[特許情報プラットフォーム](https://www.j-platpat.inpit.go.jp/)\n\n[変調装置及び復調装置 WO-A-2010/016589](https://www.j-platpat.inpit.go.jp/c1800/PU/WO-A-2010-016589/7847773A7250230D1C8D66BBF506D4E794BEF7F38B5DF2B8C11BE9225DF7BB10/50/ja)\n\n\n## GetStarted\n\nAnacondaの利用を前提として説明します。Pythonのバージョンは、Python 3.10.xを推奨します。\n\nセットアップが成功すると、コマンドラインツールの[tbskmodem](./tbskmodem.md)も同時にインストールされます。\n\n\n#### Anacondaでのセットアップ\nソースコードをgithubからcloneします。\n\n```\n\u003egit clone https://github.com/nyatla/TBSKmodem.git\n```\n\nstep4までは外部モジュールは不要です。\n\nstep4より先に進むならば、numpy,sounddeviceをインストールしてください。\nサウンドの再生やキャプチャに必要です。\n```\n\u003econda install -c anaconda numpy\n\u003econda install -c conda-forge python-sounddevice\n```\n\n#### pipからのセットアップ\n\nLinux環境のpipでセットアップする場合はportaudioも必要になります。\n\n```\n$sudo apt-get install portaudio19-dev\n$pip install tbskmodem\n```\nportaudioをセットアップできればWindows下でも利用できるはずです。\n\n\n\n\n### サンプルプログラムの場所\n\nサンプルプログラムはTBSKmodem/getstartedディレクトリにあります。\n```\n\u003e cd getstarted\n```\n\n#### step1. データをwaveファイルに変換\nstep1.modulate.pyは、ビット値を変調することができます。\n\n```\n\u003e python step1_modulate.py\nImported local library.\n[WARN] Imported local library.\n\u003e\n```\nこのスクリプトは変調した振幅信号をwavファイルに保存します。\n出力ファイル名は、step1.wavです。\n\n`[WARN] Imported local library.`と表示されましたか？心配は不要です。\nこの表示は、ライブラリではなく、ローカルディレクトリにあるtbskmodemパッケージをリンクした時に表示されるメッセージです。\n\nメイン関数を見てみましょう。\n```\ndef main():\n    tone=TbskTone.createXPskSin(10,10).mul(0.5)    # SSFM DPSK\n    payload=[0,1,0,1,0,1,0,1]*16 # 16byte\n    carrier=8000\n\n    #modulation\n    mod=TbskModulator(tone)\n    src_pcm=[i for i in mod.modulateAsBit(payload)]\n\n    #save to wave\n    with open(\"step1.wav\",\"wb\") as fp:\n        PcmData.dump(PcmData(src_pcm,16,carrier),fp)\n```\n\nこのスクリプトは、まず伝送シンボルに相当するTraitToneオブジェクトを生成します。\n次に、変調器のTbskModulatorオブジェクトを生成して、modulateAsBit関数で変調します。\n変調するのはビット値(1 or 0)の配列で、合計8*16=128ビットです。\n\nmodulateAsBit関数の戻り値は、変調した振幅値(float)を返すイテレータです。これをリストにして、最後にWaveファイルにして保存します。\n\n#### step2. wavファイルから復調\n\nstep2.modulate.pyは、作成したwavファイルを元のビット列に戻します。\n```\n\u003e python step2_demodulate.py\n[WARN] Imported local library.\n[0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]\n\u003e\n```\n当然のように、元のビット列に戻るはずです。\n\nメイン関数を見てみましょう。\n```\ndef main():\n    wav=None\n    with open(\"step1.wav\",\"rb\") as fp:\n        wav=PcmData.load(fp)\n\n    tone=TbskTone.createXPskSin(10,10)\n    demod=TbskDemodulator(tone)\n\n    ret=demod.demodulateAsBit(wav.dataAsFloat())\n    print([i for i in ret] if ret is not None else None)\n```\n信号を格納したWaveファイルはstep1で作成したstep1.wavです。これを読み出します。\n次にトーン信号を作り、そこから復調器のTbskDemodulatorを作り、demodulateAsBit関数で復調します。\n\ndemodulateAsBit関数はビット列をintで返すイテレータです。これをリストにして表示します。\n\n\nイテレータは信号が成立しなくなるまで値をビット値を返し続けます。(信号終端についての疑問はここでは一旦忘れます。)\n\n\n#### step3. バイトデータの変調と復調\n\nバイト値を送受信する関数も当然実装済みです。\nstep3_bytedata.pyは、bytes値の変調と復調を実行します。\n\n```\n\u003e python .\\step3_bytedata.py\n[WARN] Imported local library.\n[b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9']\n\u003e \n```\n\nメイン関数を見てみましょう。\n\n```\ndef main():\n    tone=TbskTone.createXPskSin(10,10).mul(0.5)    # SSFM DPSK\n    payload=b\"0123456789\" # 10byte\n    carrier=8000\n\n    #modulation\n    mod=TbskModulator(tone)\n    src_pcm=[i for i in mod.modulate(payload)]\n\n    #save to wave\n    wav=PcmData(src_pcm,16,carrier)\n    with open(\"step3.wav\",\"wb\") as fp:\n        PcmData.dump(wav,fp)\n\n    #demodulate to bytes\n    demod=TbskDemodulator(tone)\n    ret=demod.demodulateAsBytes(wav.dataAsFloat())\n    print([i for i in ret] if ret is not None else None)\n```\n\nstep1とstep2を合体したような構造です。\nmod.modulate関数に注目してください。ここで、payloadにbytesをそのまま渡しています。\nそして、demod.demodulateAsBytesにも注目してください。データを渡すと、Bytesにして返してくれそうな関数です。\n\n入力は連続するbytes値なのに戻り値が1byte単位のbytes型なのは不自然な気もしますが、そういうものです。\n\n#### step4. 文字列の変調と復調\n\nstep4_text.pyは、文字列の変調と復調を実行します。\n\n```\n\u003e python .\\step4_text.py    \n[WARN] Imported local library.\n['ア', 'ン', 'タ', 'ヤ', 'ル', 'ー', 'ニ', 'ャ']\n\u003e\n```\nメイン関数を見てみましょう。step3とほとんど変わりません。\n\n```\ndef main():\n    tone=TbskTone.createXPskSin(10,10).mul(0.5)    # SSFM DPSK\n    payload=\"アンタヤルーニャ\" # 8byte\n    carrier=8000\n\n    #modulation\n    mod=TbskModulator(tone)\n    wav=PcmData([i for i in mod.modulate(payload)],16,carrier)\n    #save to wave\n    with open(\"step4.wav\",\"wb\") as fp:\n        PcmData.dump(wav,fp)\n\n    #demodulate to bytes\n    demod=TbskDemodulator(tone)\n    ret=demod.demodulateAsStr(wav.dataAsFloat())\n    print([i for i in ret] if ret is not None else None)\n```\n変調部分はmod.modulateそのままです。\n関数呼び出しの変更点は、復調部分でdemodulateAsStr関数が使われているところです。\n\n変調器と復調器は、それぞれ、bit配列,文字列,Hex string,bytes,uint8配列を引数に取る関数があります。\n\n\n#### step5. マイク入力のテスト\n\nstep5_microphone.pyで、サウンドデバイスがpythonからアクセスできるかテストしましょう。\n\n注意:WSL、VirtualBoxなどの仮想システムでは、サウンドデバイスにノイズが混じるため、通信が成立しないことがあります。\n\n```\n\u003e python .\\step5_microphone.py\n[WARN] Imported local library.\nPress [ENTER] to stop.\nVolume meter\n###\n```\n\n\"#\"で示されるバーグラフが動いていれば、pythonは正常にマイクを認識しています。\n\nうまく認識できない場合は次の事を試してください。\n\n1. マイクがPCに接続されているか確認する。\n2. スクリプトのdevice_idパラメータを変更する(1,2,3...)\n3. 他のプログラムでマイクを認識しているか確認する。\n4. もっと大きな音を出す。\n\nテストが終わったら、ENTERでプログラムを停止します。\n\n\n#### step6. リアルタイム送受信\n\n仕上げに、step6_realtime_receive.pyでリアルタイムに信号を復調します。\nマイクの準備は宜しいですか？\n\n注意:WSL、VirtualBoxなどの仮想システムでは、サウンドデバイスにノイズが混じるため、通信が成立しないことがあります。\n\n```\n\u003e python .\\step6_realtime_receive.py\n[WARN] Imported local library.\n160.0 bps\nPlay step6.wave in your player.\nStart capturing\n\u003eアンタヤルーニャ\nEnd of signal.\n\u003e\n```\n\n実行したディレクトリに、step6.wavが生成されています。\nこのWaveファイルをpythonに聞かせてください。\n復調した文字列が表示されます。\n\nところで、受信した信号の終端はどこなのか？という疑問が残されたままです。\nTBSKでは、信号を検知した後、信号強度が閾値を超えていれば、それが何であっても延々と値を復調し続けます。\n上位の通信仕様でパケット長を固定したり、長さパラメータを初めに送信するなどして対処してください。\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnyatla%2FTBSKmodem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnyatla%2FTBSKmodem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnyatla%2FTBSKmodem/lists"}