ネコと和解せよ

TBSKmodemをブラウザ他でも使えるようにした。

オーディオモデムのTBSKmodemをブラウザでも動くようにしました。

お試しはこちらから。スマホタブレットなどでも動きます。
PCとスマホを用意して、PCから送信→スマホで受信のようにするとスムーズに遊べます。

ライブデモ → https://nyatla.jp/tbskmodem/

iOSだけは少々問題があり、マイクを許可した後にアドレスバーから一度マイクデバイスのON/OFFをしないとうまくデータを受信できません。(Safariのバグのような気がする。)

TBSKmodemについて

TBSK modemは、近距離で低速な音響通信機能を提供する通信ライブラリです。
nyatla.hatenadiary.jp

その他の対応プラットフォーム

現状、Python/C#(WIindows)/C++(WASM/Linux/Windows)/JavaScript(ブラウザ)で動作するコードがあり、相互に通信ができます。APIはそれほど難しくないので遊んでみて下さい。

サンプルをいくつか紹介します。

Python

TBSKmodem/getstarted at master · nyatla/TBSKmodem · GitHub

文字列を変調・復調します。UTF8を直接扱えるのがチャームポイントです。

import sys,os
try:
    from tbskmodem import TbskModulator,TbskDemodulator,XPskSinTone,PcmData
except ModuleNotFoundError:
    sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
    from tbskmodem import TbskModulator,TbskDemodulator,XPskSinTone,PcmData
    print("[WARN] Imported local library.")

def main():
    tone=XPskSinTone(10,10).mul(0.5)    # SSFM DPSK
    payload="アンタヤルーニャ" # 8byte
    carrier=8000

    #modulation
    mod=TbskModulator(tone)
    wav=PcmData([i for i in mod.modulate(payload)],16,carrier)
    #save to wave
    with open("step4.wav","wb") as fp:
        PcmData.dump(wav,fp)

    #demodulate to bytes
    demod=TbskDemodulator(tone)
    ret=demod.demodulateAsStr(wav.dataAsFloat())
    print([i for i in ret] if ret is not None else None)

if __name__ == "__main__":
    main()

C#

TBSKmodemCS/windows/TBSKmodem at master · nyatla/TBSKmodemCS · GitHub

pythonのサンプルと同じです。APIもほぼ同じです。
C#版はオーディオアクセスにNAudioを利用します。

using System.Text;
using jp.nyatla.kokolink.protocol.tbsk.tbaskmodem;
using jp.nyatla.kokolink.protocol.tbsk.toneblock;
using jp.nyatla.kokolink.utils.wavefile;


var tone = new XPskSinTone(10, 10).Mul(0.5);//    # SSFM DPSK
var payload = "アンタヤルーニャ";
uint carrier = 8000;

//# modulation
var mod = new TbskModulator(tone);
IList<double> src_pcm = mod.Modulate(payload).ToList();

//# save to wave
var wav = new PcmData(src_pcm, 16, carrier);
using (var stream = File.Open("./step4.cs.wav", FileMode.Create, FileAccess.Write))
{
    var pcm = new PcmData(src_pcm, 16, (uint)carrier);
    PcmData.Dump(pcm, stream);
}

//# demodulate to bytes
var demod = new TbskDemodulator(tone);
var ret = demod.DemodulateAsStr(wav.DataAsFloat());

foreach (var i in ret!)
{
    Console.Write(String.Format("{0}", i));
}

C++

TBSKmodemCpp/windows/TBSKmodemCpp at master · nyatla/TBSKmodemCpp · GitHub

C++版は文字列ではなくbyte/bit値を直接扱います。new/delete、浮動小数点を使用しているため、いまのところは小規模MCUでは動きません。

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <stdlib.h>
#include "../../../src/tbskmodem/tbskmodem.h"
#include <memory>
#include <vector>
using namespace TBSKmodemCPP;
using namespace std;
int main()
{
	{
		auto tone = make_shared<XPskSinTone>(8, 10);//10 point/cycle * 100 
		auto preamble = make_shared<CoffPreamble>(tone);
		auto mod = make_shared<TbskModulator>(tone, preamble);
		std::vector<int> bits{ 0,1,0,1,0,1,0,1 };
		auto src = std::make_shared<PyIterator<int>>(bits);
		auto a = std::make_shared<RoStream<int>>(src);
		auto c = mod->Modulate("Hello");
		auto d = Functions::ToVector<double>(c);
		FileWriter fw("./test2.wav");
		PcmData pcm(d, 16, 8000);
		PcmData::Dump(pcm, fw);
	}
	_CrtDumpMemoryLeaks();
	return 0;
}

JavaScript

TBSKmodemJS/getstarted at master · nyatla/TBSKmodemJS · GitHub

C++版から作成したWASMを包括したスタンドアロンスクリプトを使う場合です。

<!doctype html>
<html lang=en-us>
<head>
  <meta charset=utf-8>
  <meta content="text/html; charset=utf-8" http-equiv=Content-Type>
  <title>TBSKmodemJS - modulation/demodukation.</title>
</head>
<body>
    <h1>Modulation/Demodulation test.</h1>
    See console log.
    <script async src="../dist/tbskmodem.js"></script>
    <script>
        window.addEventListener('load', function () {
          TBSKmodemJS.load().then((tbsk)=>{
                console.log(tbsk.version);
                var tone = new tbsk.XPskSinTone(10,10);
                var preamble = new tbsk.CoffPreamble(tone);
                let mod = new tbsk.TbskModulator(tone, preamble);
                let farray = mod.modulate([1,2,3]);
                mod.dispose();
                console.log(farray.length);

                let demod=new tbsk.TbskDemodulator(tone,preamble);
                let demod_src=demod.demodulate(farray);
                console.log(demod_src);


                tone.dispose();
                preamble.dispose();
                demod.dispose();
          });
        });
  </script>
</body>
</html>

nodeJSを使うサンプルもあります。

import {TBSKmodemJS} from "tbskmodem-js"


TBSKmodemJS.load().then((tbsk)=>{
    console.log(TBSKmodemJS.version);
    console.log(tbsk.version);}
)

JavaScript版は、オーディオデバイスにwebAudioを使います。

今後の予定

小規模MCU、プロトタイピングプラットフォーム向けに実装を進めていきます。