RSS Twitter Facebook
DTM / シンセサイザー / VST / WebMusic 関係の技術情報を発信しています

Products : ユーロラックモジュラー「RedLine」販売中

ユーロラック・モジュラーシンセサイザー「RedLine」を販売開始しました!

ユーロラック「RedLine」



2019/01/16 (2019年01月 のアーカイブ)

サンプルコードは GitHub で Unlicense でどうかな?

Twitter Google+ Facebook

ちゃんと纏まっているアプリではなくて、ちょっとしたコードフラグメントやサンプルコードのようなものを GitHub に置く時、ライセンスの選択ってどうやってますか?

だいたいいつもテンプレートで選べるメジャーな選択肢の中では一番緩いと思われる MIT License にしていたのですが、MIT にも表示義務はあるので本当のところは、使い方の Tips 的なコードフラグメントに MIT License が付いていても気にする人は困る事があるだろうなとは思っていたんです。

クリエイティブ・コモンズの CC0 とか、ちょっとネタ的ではあるけど WTFPL(Do What The Fuck You Want To Public License) あたりが適当かなと思うのだけど、GitHub のテンプレートには無いから自分でコピーしてくるのが面倒くさい。

と思っていたのだけど、良いのがあるのを知らなかった。

それが、Unlicense

法的制約に則りつつパブリックドメインに可能な限り近づけるという クリエイティブ・コモンズ CC0 と目指すところは同じようです。

CC0 の方が洗練されているとか、色々意見もあるようだけど、サンプルコードなんかにはこれで良くないかな?
GitHub のライセンステンプレートの一番最後に載っていたのに今頃気づいた。

という事で今後は Unlicense を推します。
https://github.com/g200kg/audioworklet-in-one-file

Unlicense 全文

This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.

In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <http://unlicense.org/>


Posted by g200kg : 9:22 PM : PermaLink

2019/01/15 (2019年01月 のアーカイブ)

[Web Audio API] AudioWorklet を 1 ファイルで書く方法

Twitter Google+ Facebook

AudioWorklet は Web Audio API でユーザーが自分独自のカスタムノードを作成できるようにするための仕組みで、プログラムのメインスレッドで走らせる AudioWorkletNode と音声処理スレッドで実行する AudioWorkletProcessor と呼ばれる部分で構成されます。

基本的な書き方としては AudioWorkletNode 側と AudioWorkletProcessor 側を別ファイルの ".js" で書くというスタイルが標準的で、これは別に悪い事ではないのですが前身となった ScriptProcessor が単に関数を定義するだけで使えたのに比べると、ちょっと試しに軽く使いたい時に、別ファイルを準備するのがちょっと面倒くさいと感じてしまいます (大規模なプログラムを書くつもりなら分けておいた方が良いと思うんですが)。

という事で、1ファイルでメインプログラムとプロセッサをまとめて書く方法を幾つか試してみます。


今回ベースにするコード

まずはベースとして前回の記事 ([WebAudio API] AudioWorklet の使い方) で書いた AudioWorklet のオーバードライブを使用します。

プロセッサ側のコードは次のようになっています。

overdrive-proc.js

class OverDrive extends AudioWorkletProcessor {
    static get parameterDescriptors () {
        return [{
            name: 'drive',
            defaultValue: 0,
            minValue: 0,
            maxValue: 1,
            automationRate: "k-rate"
        }];
    }
    process (inputs, outputs, parameters) {
        let input = inputs[0];
        let output = outputs[0];
        let drv = Math.pow(0.05,Math.abs(parameters.drive[0]));
        for (let channel = 0; channel < output.length; ++channel) {
            for (let i = 0; i < output[channel].length; ++i) {
                var d=input[channel][i];
                if(d<0)
                    output[channel][i]=-Math.pow(-d,drv);
                else
                    output[channel][i]=Math.pow(d,drv);
            }
        }
        return true;
    }
}
registerProcessor("OverDrive", OverDrive);

プロセッサのコードは "OverDrive" クラスを定義して、registerProcessor() で名前を付けて登録する、という処理になっています。 このプロセッサを使うメインプログラムとして取り合えず簡単なものを書いたものが次のコードです。


<!doctype html>
<html lang="en">
<body>
<audio id="soundsrc" src="./loop.wav" controls loop></audio><br/>
Drive : <input id="drive" type="range" min="0" max="1" step="0.01" value="0"/><br/>
<script>
window.onload = (async ()=>{
    audioctx = new AudioContext();
    await audioctx.audioWorklet.addModule('overdrive-proc.js');
    const src = new MediaElementAudioSourceNode(
        audioctx,{mediaElement:document.getElementById('soundsrc')}
    );
    const overdrive = new AudioWorkletNode(audioctx, 'OverDrive');
    const paramDrive = overdrive.parameters.get('drive');
    src.connect(overdrive).connect(audioctx.destination);

    document.getElementById("drive").addEventListener("input",(ev)=>{
        audioctx.resume();
        paramDrive.value=ev.target.value;
    })
});
</script>
</body>
</html>

このコードのテストページ


音源を <audio> タグでドキュメント内に置いて MediaElementAudioSourceNode で読み込む方法で、オーバードライブを経由して鳴らします。ちなみに window.onload で初期化をしていますが、プライバシーポリシー制限でユーザー操作が無い状態で作った AudioContext は "suspend" 状態ですので、スライダーを触ったら resume() するという事をやっています。

プロセッサのファイル "overdrive-proc.js" を読み込んでいるのが 9 行目、audioctx.audioWorklet.addModule() です。


取り合えずプロセッサ側のコードを文字列として埋め込んでみる

まずはファイル "overdrive-proc.js" の内容をそのまま文字列に入れておいて DataURI 経由でアクセスするという方法です。38 行目の処理、
await audioctx.audioWorklet.addModule('data:text/javascript,'+encodeURI(overdriveproc));
がそれです。'data:text/javascript,' に続けてプロセッサの文字列をエスケープしてくっ付ける事で、URL としてアクセスできるようにしています。

単純に文字列としてコードを入れるのは、昔の JavaScript だと文字列が改行で途切れないように全ての行末に「\」を付ける必要があったりしてあまり実用的ではなかったのですが、ES6 でテンプレート文字列が使えるようになってからは、コード全体を 「`」で囲むだけですのでこれでもまあいけなくはないです。

このコードのテストページ

<!doctype html>
<html lang="en">
<body>
<audio id="soundsrc" src="./loop.wav" controls loop></audio><br/>
Drive : <input id="drive" type="range" min="0" max="1" step="0.01" value="0"/><br/>
<script>
const overdriveproc =`
class OverDrive extends AudioWorkletProcessor {
    static get parameterDescriptors () {
        return [{
            name: 'drive',
            defaultValue: 0,
            minValue: 0,
            maxValue: 1,
            automationRate: "k-rate"
        }];
    }
    process (inputs, outputs, parameters) {
        let input = inputs[0];
        let output = outputs[0];
        let drv = Math.pow(0.05,Math.abs(parameters.drive[0]));
        for (let channel = 0; channel < output.length; ++channel) {
            for (let i = 0; i < output[channel].length; ++i) {
                var d=input[channel][i];
                if(d<0)
                    output[channel][i]=-Math.pow(-d,drv);
                else
                    output[channel][i]=Math.pow(d,drv);
            }
        }
        return true;
    }
}
registerProcessor("OverDrive", OverDrive);
`;
window.onload = (async ()=>{
    audioctx = new AudioContext();
    await audioctx.audioWorklet.addModule('data:text/javascript,'+encodeURI(overdriveproc));
    const src = new MediaElementAudioSourceNode(
        audioctx,{mediaElement:document.getElementById('soundsrc')}
    );
    const overdrive = new AudioWorkletNode(audioctx, 'OverDrive');
    const paramDrive = overdrive.parameters.get('drive');
    src.connect(overdrive).connect(audioctx.destination);

    document.getElementById("drive").addEventListener("input",(ev)=>{
        audioctx.resume();
        paramDrive.value=ev.target.value;
    })
});
</script>
</body>
</html>

特殊なタイプのスクリプトとして HTML 内に埋め込む方法

他のやり方としては HTML 内に特殊なスクリプトとして埋め込む方法があります。スクリプトのタイプをそのまま実行される JavaScript と解釈されないように特殊な名前で定義します。

こういうやり方は WebGL の GLSL シェーダーを HTML 内に書く時などにも使われていて 'x-shader/x-vertex' とか 'x-shader/x-fragment' などとする事が多いようです。'x-' を付けるのは標準のタイプではない、という意味になります。 ここでは、AudioWorklet 用の JavaScript なので、
<script type="x-audioworklet/javascript">
としました。中身は document.getElementById('id').innerHTML で取ってこれますので処理としては文字列とそれほど違いはないですね。

ここの表示ではプロセッサのコードが一応 JavaScript としてシンタックスハイライトが効いているので文字列の場合よりかなり読みやすいですが、これはエディタによると思います。VScode では未知のスクリプト扱いで駄目でした。

このコードのテストページ

<!doctype html>
<html lang="en">
<body>
<audio id="soundsrc" src="./loop.wav" controls loop></audio><br/>
Drive : <input id="drive" type="range" min="0" max="1" step="0.01" value="0"/><br/>

<script id="overdriveproc" type="x-audioworklet/javascript">
class OverDrive extends AudioWorkletProcessor {
    static get parameterDescriptors () {
        return [{
            name: 'drive',
            defaultValue: 0,
            minValue: 0,
            maxValue: 1,
            automationRate: "k-rate"
        }];
    }
    process (inputs, outputs, parameters) {
        let input = inputs[0];
        let output = outputs[0];
        let drv = Math.pow(0.05,Math.abs(parameters.drive[0]));
        for (let channel = 0; channel < output.length; ++channel) {
            for (let i = 0; i < output[channel].length; ++i) {
                var d=input[channel][i];
                if(d<0)
                    output[channel][i]=-Math.pow(-d,drv);
                else
                    output[channel][i]=Math.pow(d,drv);
            }
        }
        return true;
    }
}
registerProcessor("OverDrive", OverDrive);
</script>

<script>
window.onload = (async ()=>{
    audioctx = new AudioContext();
    await audioctx.audioWorklet.addModule(
        'data:text/javascript,'
        + encodeURI(document.getElementById('overdriveproc').innerHTML)
    );
    const src = new MediaElementAudioSourceNode(
        audioctx,{mediaElement:document.getElementById('soundsrc')}
    );
    const overdrive = new AudioWorkletNode(audioctx, 'OverDrive');
    const paramDrive = overdrive.parameters.get('drive');
    src.connect(overdrive).connect(audioctx.destination);

    document.getElementById("drive").addEventListener("input",(ev)=>{
        audioctx.resume();
        paramDrive.value=ev.target.value;
    })
});
</script>
</body>
</html>

普通の JavaScript のクラスとして宣言してしまう方法

前の 'x-audioworklet' あたりの方法がまあ妥当かと思いつつ、最後にもうひとつトリッキーなやりかたで、普通に JavaScript のクラスとして書いてしまう方法もなくはないです。

もちろんそのままプロセッサのコードを メインのコード内に書いても動かないので少し細工します。

まずプロセッサ用のクラスは 'AudioWorkletProcessor' クラスを継承して作成しますが、この AudioWorkletProcessor はメインスレッド側には存在しないため、そもそもエラーになるのでダミーを宣言しておきます。
class AudioWorkletProcessor{}
それから次の 'addAudioWorklet()' がメインスレッド側のクラスをプロセッサとして登録するための関数です。やっている事は宣言されているクラスオブジェクトから 'toString()' で文字列化して、後は文字列として埋め込む方法と違いはありません。

ただし引数として取るのはクラスオブジェクトそのものですので、プロセッサ登録のための 'registerProcessor()' は自前で追加しています。また登録される名前はクラス名そのものになります。ここではクラス 'OverDrive' で宣言しているのでノードを作成する時も
new AudioWorkletNode(context, 'OverDrive')
となります。

addAudioWorklet()の戻り値は 'addModule()' と同じく Promise ですので必要なら await で待つなりしてください。

このコードのテストページ

<!doctype html>
<html lang="en">
<body>
<audio id="soundsrc" src="./loop.wav" controls loop></audio><br/>
Drive : <input id="drive" type="range" min="0" max="1" step="0.01" value="0"/><br/>

<script>
// Register Class as an AudioWorklet Processor
class AudioWorkletProcessor{}
function addAudioWorklet(context, proc){
    var f=`data:text/javascript,${encodeURI(proc.toString())}; registerProcessor("${proc.name}",${proc.name})`;
    return context.audioWorklet.addModule(f);
}

// AudioWorklet Processor Class
class OverDrive extends AudioWorkletProcessor {
    static get parameterDescriptors () {
        return [{
            name: 'drive',
            defaultValue: 0,
            minValue: 0,
            maxValue: 1,
            automationRate: "k-rate"
        }];
    }
    process (inputs, outputs, parameters) {
        let input = inputs[0];
        let output = outputs[0];
        let drv = Math.pow(0.05,Math.abs(parameters.drive[0]));
        for (let channel = 0; channel < output.length; ++channel) {
            for (let i = 0; i < output[channel].length; ++i) {
                var d=input[channel][i];
                if(d<0)
                    output[channel][i]=-Math.pow(-d,drv);
                else
                    output[channel][i]=Math.pow(d,drv);
            }
        }
        return true;
    }
}

// Main Program
window.onload = (async ()=>{
    audioctx = new AudioContext();
    await addAudioWorklet(audioctx, OverDrive);
    const src = new MediaElementAudioSourceNode(
        audioctx,{mediaElement:document.getElementById('soundsrc')}
    );
    const overdrive = new AudioWorkletNode(audioctx, 'OverDrive');
    const paramDrive = overdrive.parameters.get('drive');
    src.connect(overdrive).connect(audioctx.destination);

    document.getElementById("drive").addEventListener("input",(ev)=>{
        audioctx.resume();
        paramDrive.value=ev.target.value;
    })
});
</script>
</body>
</html>

これならエディタで確実にシンタックスハイライトが効くというのが良い所です。
メインプログラムのスコープ内にクラスオブジェクトとして存在してしまっているのが無駄と言えば無駄ですが、許せる範囲でしょうか。

Posted by g200kg : 12:20 AM : PermaLink

2019/01/14 (2019年01月 のアーカイブ)

[WebAudio API] AudioWorklet の使い方

Twitter Google+ Facebook

さて、2019 年になって ScriptProcessor の後継とされる AudioWorklet が Chrome で動き始めてからもう一年くらい経ちましたかね。まだまだガリガリ使われているという感じでもないのは、以前の ScriptProcessor に比べると構造が複雑になってちょっととっつきにくくなったからでしょうか。少しハードルが上がった感はありますね。

それに現状は Web Audio API の仕様とブラウザの実装がまだ少し乖離している所が残っているので気を付けないとハマるかも知れません。

とは言っても ScriptProcessor がいつまであるかもわからないし、そろそろちゃんと使わないとですね。

という事でまずはサンプルを書いてみました。

AudioWorklet (OverDrive)


たいしたものではないですが、これはオーバードライブエフェクトを AudioWorklet で実装したものです。[Play]を押すと音楽が流れて [Drive] のツマミでかかり具合を調整できます。


ソースコード overdrive-proc.js


class OverDrive extends AudioWorkletProcessor {
    static get parameterDescriptors () {
        return [{
            name: 'drive',
            defaultValue: 0,
            minValue: 0,
            maxValue: 1,
            automationRate: "k-rate"
        }];
    }
    process (inputs, outputs, parameters) {
        let input = inputs[0];
        let output = outputs[0];
        let drv = Math.pow(0.05,Math.abs(parameters.drive[0]));
        for (let channel = 0; channel < output.length; ++channel) {
            for (let i = 0; i < output[channel].length; ++i) {
                var d=input[channel][i];
                if(d<0)
                    output[channel][i]=-Math.pow(-d,drv);
                else
                    output[channel][i]=Math.pow(d,drv);
            }
        }
        return true;
    }
}
registerProcessor("OverDrive", OverDrive);


AudioWorklet では、音声処理を実行するプロセッサはメインのプログラムとは別ファイルで用意するのが基本です。

この 'overdrive-proc.js' がプロセッサ部分になりますが、AudioWorkletProcessor クラスから派生した class を定義し、registerProcessor() で登録します。プロセッサはメインプログラムとは別のオーディオ処理専用のスレッドで実行され、変数を受け渡したりというメインプログラムの世界とは直接的なやりとりはできません。

ここで定義したクラス内の process() 関数が実際の処理を行います。引数の inputs が音声信号の入力の配列、outputs が音声信号の出力の配列、parameters はこのノードが持っているパラメータの値を表します。OverDrive のようなエフェクター的なノードの場合はデフォルト状態の入力が 1 本、出力が 1 本で良いです(ステレオ音声等のマルチチャンネルも入力の数としては 1 本です)。

なので inputs[0] および outputs[0] が処理すべき入出力になります。入出力はブロック (128 サンプル) 毎に渡されますので、各チャンネルの各サンプルを入力から取得して処理を行い出力に渡しています。

ちなみにオーバードライブ処理というと一般的には tanh 関数なんかが良く使われるのですが、ここで行っているのは

\(output = Math.pow(input, 定数)\)

という処理を正負対称にくっつけたものを使っています。ここで定数を 1.0 ~ 0.05、つまり実数乗根とすると 1.0 で歪み無し、小さくなる程すぐに 1.0 に漸近するカーブになるので歪みが大きくなります。更にパラメータの 0.0 ~ 1.0 に対して冪乗の定数は

\(Math.pow(0.05, パラメータ)\)

で 1.0 ~ 0.05 の範囲にマップしています。入力に対する出力カーブは次のようになります。
まあこのあたりは好みもあるので適当ですが。

後は process() の最後が return true になっている所に注目です。とりあえず今は process() は true を返す、という事で良いですがこれはまた後述。

それから、static get parameterDescriptors() いうメソッドがありますが、これはこの OverDrive ノードが持っているパラメータを表しています。Oscillator ノードの frequency や Gainノードの gain のようなものです。

ここではdrive という 0 ~ 1 の範囲のパラメータを一つだけ持っていて animationRate が "k-rate" である事が宣言されています。

animationRate は "k-rate" と "a-rate" があり、"a-rate" はパラメータが 1 回の process() の呼び出し内でサンプル単位で変化し(する可能性があり)、"k-rate" はブロック単位なので process() 呼び出し内では必ず固定値になります。"a-rate" だともう少しコード量が増えてしまうし、"k-rate" より処理が重くなります。


ソースコード メインプログラム (html)

さて、プロセッサは登録しましたがこれを使う側です。
async function Init(){
    audioctx = new AudioContext();
    buffer = await LoadSample(audioctx, "./loop.wav");
    await audioctx.audioWorklet.addModule("overdrive-proc.js");
    overdrive = new AudioWorkletNode(audioctx,"OverDrive");
    overdrive.drive = overdrive.parameters.get("drive");
    vol = new GainNode(audioctx,{gain:0.5});
    analyser = new AnalyserNode(audioctx);
    src = new AudioBufferSourceNode(audioctx, {buffer:buffer, loop:true});

    src.connect(overdrive).connect(vol).connect(analyser).connect(audioctx.destination);

    //....
}
初期化の部分だけですが、async/await で書いています。
  • AudioContext の作成
  • 音源のロード
の次に
  • addModule
で、さっき作った "overdrive-proc.js" を追加していますが、この API は Promise を返しますので await で終了を待っています。これでメインプログラム側で OverDrive が使えるようになります。 そして
  • overdrive = new AudioWorkletNode(audioctx,"OverDrive");
が実際に AudioWorklet のノードを作成している部分です。これにより普通のノードとして使用できる AudioWorklet ノードが作成され、自動的にユーザーからは見えないオーディオ処理スレッド側では対応する overdrive-proc.js の OverDrive 処理のインスタンスが生成されます。

次の
  • overdrive.drive = overdrive.parameters.get("drive");
は、OverDrive ノードが持っているパラメータにアクセスしやすくするために overdrive ノードのプロパティにくっつけている処理です。これで、GainNode.gain と同様に OverDrive.drive という形式でアクセスできます。これについてはまた後述。

最後の行で、ノードの接続は

src(BufferSource音源) => overdrive(AudioWorklet) => vol(メインボリューム用Gain) => analyser(波形表示用) => destination

と普通のノードと同様に connect() で接続しています。後は音源用のデータを fetch で読んだり、ツマミをいじった時に オーバードライブのパラメータを変更したり、出てきた音の波形を Canvas で描いたりしていますけど、今までの WebAudio のプログラムと違う所は無いと思います。


気を付けないといけない事

今はまだ仕様と実装が完全に一致していない部分があったりするので幾つか注意点があります。
  • プロセッサの process() の戻り値は、ノードのライフタイムを制御します。

    仕様上は false を返した場合、ノードに信号が入力されている間だけ動作を続け、接続が無くなると自動的にノードが破棄される、という事になっています。これはその内、実装に反映されるのではないかと思いますが、今は false を返すとノードが止まってしまうので必ず true を返して動かしっぱなしにする必要があります。

  • 作成した AudioWorkletNode のパラメータにアクセスするには
    overdrive.parameters.get("drive")
    のように parameters.get() を経由する必要があります。例えば OscillatorNode.frequency や DelayNode.detayTime のようには行かない所が、まあ事情はあると思いますがちょっと残念ではありますね。
    このサンプルではせめて、という事でメインプログラム側でノードを作った後、
    overdrive.drive = overdrive.parameters.get("drive")
    とやって overdrive.drive でアクセスできるようにしています。これがプロセッサ側のコードでできれば良いんですけどね。

    アクセスした先のオブジェクトは普通の AudioParam ですので、.value に値を代入したり、setValueAtTime() などのオートメーション関数を使ったり、他のノードの出力を接続して変調を掛けたりという事は通常通りできます。

  • この例では使っていないのですが、AudioWorklet のノードのパラメータに作成と同時に初期値を渡したい時、少し書式が違います。

    例えば GainNode を作成する時、
    new GainNode(audioctx, {gain:0.5})
    とやって作成時に gain を 0.5 に設定するなんて事ができますが、AudioWorklet ノードの場合、例えば OverDrive の drive を 0.5 に設定するなら、
    new AudioWorkletNode(audioctx,"OverDrive",{drive:0.5});
    ではなくて、
    new AudioWorkletNode(audioctx,"OverDrive",{parameterData:{drive:0.5}});
    のようになります。これが一応仕様上定められた書き方ですが、仕様書内の EXAMPLE コードでも書き方が違っている部分があったりするので混乱しやすい所です。

  • AudioWorklet だけの問題ではないですが、去年導入された Privacy Policy の影響で WebAudio で音を出すには最初にユーザーの操作が無くてはいけません。AudioWorklet は動き始める前に AudioContext を使って必要なモジュールの登録処理等が必要ですので、処理の順序を考えるのが少し面倒になった感があります。まあちゃんと考えれば良いのですけど。

  • その内修正は入ると思いますが、基本的に Web Audio API の仕様書内にある EXAMPLE はまだちゃんと整備されていないのでそのままでは動かないものが多いです。

    今のところ実際に動作するコードのサンプルとして一番信頼できるのは、Google の WebAudio 開発者である @hoch さんが ChromeLabs で公開している Audio Worklet のサンプルページ です。

という事で、まだ少し気を付けつつ、ではありますけど AudioWorklet もそろそろガシガシ使えるフェーズに入りつつあるんじゃないですかね。

Posted by g200kg : 3:40 AM : PermaLink

2019/01/09 (2019年01月 のアーカイブ)

Frizing でひっかかりやすい所

Twitter Google+ Facebook

IoT とか Make 界隈で良く使われている Frizing という回路図エディタがあります。

基本的に初心者向けであまり大規模なものには向かないのですが、「ブレッドボード図」が簡単に描けるというのが特色で、ちょっとした工作の解説用の図を作る時なんかに重宝されています。

多分ブレッドボード図を描くために使っている人が大多数なのではないかと思いますが、機能としてはブレッドボード図、普通の回路図、基板のアートワーク、ガーバーの出力、おまけにソフトウェアのコードまでを一括管理しようというなかなか遠大な目標を持つツールです。

まあブレッドボード図が必要ないのなら Eagle なり KiCad なりを使った方が良いとは思いますが。

現在バージョンは 0.9.3b のベータ版で少しバギーな部分を残したまま既に2年半くらいアップデートが無いので今後の開発がどうなるかは少し気になる所ではあります。

frizing.org

それで、この Frizing で在り合わせの部品でブレッドボード図を描くだけなら、なかなか快適ではあるのですが、それ以上の事、独自の部品を登録したり、回路図を描いたりという事をやろうとすると色々問題点が噴出して一気にハードルが上がるんですよね。去年の年末あたりから割合ちゃんと触る機会があって、かなり問題を回避するコツを掴んできましたのでポイントだけ紹介します。


そもそも描きたい図はどれなのか


ブレッドボード図と回路図を描くのであれば、回路図=>ブレッドボード図の順序で書いた方が効率が良いです。

ブレッドボード図と回路図は一応並行で進める事もできるのですが、片方で描いた配線が反対側では仮接続のような状態になりますので、それが邪魔で回路図が書きにくい事があります。


作った部品のピンが勝手にショートしてしまう


新しい部品を登録する時、似た部品を基にして画像だけを差し替えて作る、という手法が良く紹介されているのですが、例えば GND や電源が複数本あって内部で繋がっているというような部品を基にしてしまうとその内部接続をそのまま引き継いでしまい、部品エディタの操作で修復する方法が無さそうです(見つけられないだけ?)。

例えば PIC16F883 の場合 PIN 8 と 19 がどちらも GND で内部で繋がっています。これの画像だけを差し替えて新しい部品を作っても PIN 8 に配線しようとすると 19 にもつながってしまいます。

PIN 8 につないだのに PIN 19 にも繋がっている。

PIN 数多めの部品は複数電源やGNDが複数出ている事が多いのでベースにするのは小さめのIC等で後から部品エディタで PIN 数を増やした方が良さそうです。


フォントの大きさがおかしくなる


これは良く知られた問題ですが、ブレッドボード図でも回路図でも、Inkscape で 0.1 インチグリッドに載せて SVG で描けば差し替え用の画像が描けますが、フォントの大きさが狂ってしまいます。

Inkscape が出力する SVG ファイル中のフォントサイズ指定が 'px' になっているのが Frizing で解釈できないのが原因のようなので、SVG をエディタで開いて font-size の 'px' 指定を消せばなおります。それも面倒ならすべてのオブジェクトをパスに変換してしまえば避けられます。どちらが良いかは一長一短。


回路図を描く時、ジャンクションが変なところについてしまう


特にブレッドボード図を先に書いて回路図エディタで仮接続を頼りに線を引いていると下の図のように部品の足の所にジャンクション(大き目の黒丸)が付いてしまいがちです。

これはトポロジー的には下の図のようになっていて部品間ワイヤーが2本以上集まっている所にジャンクションが付くという仕様のせいです。

下の図のように枝分かれさせたい場所にあらかじめ折れ曲がり点を作っておき、部品の足からその点に向かってワイヤーを引くという手順を取ると回避できます。なおこの時、ブレッドボード側の仮配線を一度消さないと、仮配線が邪魔で部品の足から出るワイヤーを選択できない事があります。

部品を登録する時にピン割り付けが面倒くさい

既存部品の画像を差し替えて新しい部品を作る時、各ピンがSVG画像のどこに対応するかを毎回指定するのが面倒くさいのですが、これは SVG 内のピンに相当するオブジェクトのプロパティで ID に "connector0pin"、"connector1pin" などの名前を付けておくと自動的に割り付けられます。部品エディタで各端子を表す ID 名 "connectorN" に "pin" を付けた名前です。わかりにくいですね。

なお、この機能はある程度認知されているようですが、うまく動作しないという報告もそれなりにあります。実際にやってみると、今のところおかしな挙動には遭遇していないのですが。

基板パターン図用の画像が差し替えできない

基板パターン用に使う SVG 画像は表面、裏面に配置するパッドをそれぞれまとめて "copper0"、"copper1" という名前を付けたレイヤーに入れておく必要があります。

更にこれは "プレーンSVG" 形式で保存した場合の話で、デフォルトの "Inkscape SVG" 形式で保存する場合は、各パッドをレイヤーではなく"グループ" でまとめてグループの ID に "copper0"、"copper1" という名前を付けると大丈夫なようです。

以上 Frizing で遭遇した問題の workaround 的ノウハウでした。

そもそもこのツール、ブレッドボード図を描くというニッチな所に特化している感じではありますが、コードエディタが統合されていたり、曲がりなりにもオートルーターが搭載されていたり、ガーバーが出力できたり、目指している所はなかなか凄いです。

今後に期待したいと思います。

Posted by g200kg : 2:35 AM : PermaLink

2019/01/06 (2019年01月 のアーカイブ)

google ウェブサイト翻訳ツール

Twitter Google+ Facebook

google が提供している翻訳系のサービスの1つなのですが、「ウェブサイト翻訳ツール」というのに久しぶりにアクセスしたら↓のような結果になって、どうやらサービスが終了の方向に向かっているようです。

google ウェブサイト翻訳ツール

この「ウェブサイト翻訳ツール」は良く使われているいわゆる「google 翻訳」ではなくて、サイト作成者がウェブページに仕込んでおくとページに英語やその他言語への切り替え機能を勝手に付けてくれるという無料サービスで、私も使っていたんですけどね。

下の画面の赤で囲ったのが言語切り替え用のウィジェットです。

で、これ、翻訳のエンジンは google 翻訳と同じか思いきや何か違うんです。何年か前、機械学習を使って google 翻訳の精度が飛躍的に向上した! というニュースが流れて、これでもう日本語で書いてウェブサイト翻訳ツールを入れておけば全て OK になるのか、と思ったらなんか違う。

左がgoogle翻訳で右がウェブサイト翻訳ツールです。全体的に google 翻訳の方がこなれていて、どうやら機械学習の恩恵はウェブサイト翻訳ツールには導入されなかったようです。

google翻訳でページ丸ごと翻訳するリンクとかを貼って似たような事はできなくもないのですが、それはそれで iframe の中に対応できないとか色々あって、結局待っていればウェブサイト翻訳ツールの翻訳精度が上がるのではないかと思っていたのですがね。残念ながらこういう事になったようです。

今後の方向として真っ当なやり方としては Google Cloud Translation を導入するというくらいなのかな。

まあインストール済みの翻訳ツールはそのまま動くという事なのでしばらく様子見ですけど。
---
最初のお断りのメッセージには「ネイティブで翻訳をサポートしているブラウザを使用されることをおすすめします」なんて書かれていますが、それは Chrome の事ですよね、というのはともかく、そういうブラウザ側で翻訳するのが普通になったりするんですかね? それはそれで楽な世界で良いなとは思うのですが。

Posted by g200kg : 7:20 PM : PermaLink

2018/11/27 (2018年11月 のアーカイブ)

シンセビルダーズサミットとHTML5カンファレンス

Twitter Google+ Facebook

11月24日(土)は北の丸公園の科学技術館でシンセビルダーズサミット、11月25日(日)は HTML5カンファレンスが北千住の東京電機大で開催されました。

こちらは 24日のシンセビルダーズサミットの様子。

展示会場の様子です。会場のキャパ的にはかなり限界に近いという事で開催場所をどうするかというのも課題になりつつあります。

ブース配置図。自分のブースの写真を撮っていませんでした。まあ大体いつも通りなんですけど。

武田さんのリボンコントローラ演奏。ここ数年参加されていなかったのですが復帰したらしいです。

sigboost さんの midiglue。今年6月に KickStarter での人気ぶりでも話題になったブツです。筐体も少しバージョンアップしている模様。

こちらはDigiLogさんの新作。猫モジュール CAT。ユーロラックフォームファクターですね。ソフトの書き換えでシーケンサーになったりオシレータになったりするようです。

せんとれさんのカセットテープ型のガジェット。全容を理解していないけど DJ 的な操作ができるらしい。

山下さんのユーロラックシンセ。今年の新作はフリケンシーシフターという事で、音が濁らないリングモジュレータのようなものです。これって RF 的な見方で言えばリングモッドが DSB 発生器なのに対してスペクトルの片側だけを取り出す SSB 発生器という理解だけど、構成がなかなか巧妙で面白い。

sugaさんのユークリッドシーケンストレモロ。ユーロラックシンセでは時々登場するユークリッドシーケンサーでトレモロパターンを作り出しています。

公生32+さんのフリケンシーシフター。山下さんのモジュールを追検証中。片面基板だけど美しい仕上がり。

(NIの)Massive みたいなシンセをハードで作りたいという野望を持つうーえさんの基板。VCO x 24、SVF x 8、VCA x 72、EG x 32、LFO x 32 って凄すぎる構成。製作進行中のようです。

へやのスミスさん。こちらも凄いアナログポリフォニックシンセを開発中。フルアナログの音源をCPUで制御する感じかな。今は音源部分のみという事だけど美しい仕上り。

常連原田さんのLEDバッジ群。「怪電波野郎」というノイズガジェットも基板化して展示しています。

ねや楽器さんの狂気のソルダリングシンセ。半田ごてでパターンをショートさせながら演奏します。この会場では許可が出なかったみたいだけど、実際のライブではバーナーを使ったりする模様。凄いな。

シンセサイザーコミックを出展していた帝国音楽堂さん。シンセサミットでは書籍の出展は初めてかな。

Quxさん。各種アナログシンセキットなんかがきれいにパッケージされています。








一方、翌25日の HTML5カンファレンスの様子です。ちなみに展示会場に入り浸りなのでカンファレンス自体は全然聞いてません。

北千住の東京電機大の建物入口にあるガラス張りの部屋が展示会場です。ここはどうも明るすぎて照明系には不利なんだけど。

という事でこんな展示にしています。一応レーザースキャナーが新規のブツなのだけど、HTML5との関係はあまりない。細かい事は気にしない。

webaudio.tokyo の LT からスカウトしてきた佐竹さんの楽譜をサクサク書けるIME。SFC の学生さんです。将来有望ですね。(あっきーな@dorayaki0

まあ色々と噂は聞くのだけど、なんか ZOZO スーツを配っていたので貰ってきました。

恒例のお菓子配布。

ブラウザ上で動作するクラウド型 WebGL ゲームエンジン PlayCanvas。こういうちゃんとした感じのを作っている人には頭が下がる。

サイバーエージェントブースでやっていたアンケート。IE に悩まされている人というのも相変わらずいらっしゃるようで、ご愁傷様です。

HTML5カンファレンスとは関係ないのですが、打ち上げ時に突然現れた公認資格を持っているらしいサンタ。フィンランドから来たようです。




この時期のイベントラッシュをなんとか乗り切って取り合えず一息つきました。

Posted by g200kg : 6:51 AM : PermaLink

2018/11/20 (2018年11月 のアーカイブ)

モジュラーフェスティバル TFoM 開催

Twitter Google+ Facebook

11月17日(土)-18日(日) に渋谷の東京コンタクトおよびスタジオミッションで東京モジュラーフェスティバル (TFoM) が開催されました。
昨年は展示がレッドブルスタジオでコンサートがコンタクトと少し離れていたのですが、今年はコンタクトのあるビルの上の階のスタジオが展示会場になっています。ビル内の移動で済むのは良いですね。

展示会場の様子。展示は12時~18時ですが、16時過ぎくらいから急に人が多くなりました。展示を1~2時間見た後、コンサートに突入というパターンですね。

g200kgブースはこのところ相変わらずの照明系ですが、予想外の鏡張りの壁のためレーザーをどっちに向けるべきか悩んだ末に適当なセッティング。

モジュラーシンセの体験コーナーが入口近くに設置されています。

中古モジュールのトレードコーナーもあります。

すっかりモジュラーイベントの顔になっている福産起業のモジュラー壁。

同じく大規模展示を行っている ClockFace Modular。

Hikari Instruments の新作。ガジェット風にまとめられたノイズマシンです。なかなか面白い。

ROLI ブースには Seaboard と Blocks が並べられています。

もうひとつガジェット系では Teenage Engineering の OP-Z。この小さな筐体で音と映像と照明をシーケンス制御できます。照明に関しては OP-Z が USB ホストとして動作し ENTTEC の DMX I/F 等を経由して DMX 接続するようです。

Diligent ブースの Pack Joue。楽器フェアにも出てました。パッドを載せ替え可能な MIDI コントローラですが、ゴム素材のパッドに RFID が仕込んであるようです。

こういう造形物があると目を引きます。なかなかの存在感。La Voix du Luthier。特殊スピーカーというかレゾネータと紹介していました。オンドマルトノの出力装置みたいなものですかね。

BASTL Instruments の缶たたき系のヤバイ奴。BASTL の製品としてはサーボモーターやソレノイドのドライバモジュールがあり、その応用例を示すための客寄せパンダマシンという事らしいですが、なかなか目立ってました。

1010 Music ブースにあったのですが、Teensy の IoT モジュールをユーロラック化するシールド。右上にのっかっている小さな基板が Teensy で、MIDI および Analog の入出力があり、何をさせるかは Teensy で勝手にやって、という事です。これは良いものだ。

さて、展示と並行してレクチャーなども行われました。こちらは各国の PowWow アンバサダーへのインタビュータイム。

モジュラーシンセをターゲットにした新著 Patch & Tweak の著者 Kim Bjørn さんへのインタビュー。

こちらは 4ms からのレクチャー。一つのモジュールで高機能のものが増えてきたので巨大システムよりも小さな筐体でまとめる方向への流れなんじゃないかというような話で、小さめのフレームをプッシュ。

展示の後は、地下の東京コンタクトでライブの時間です。前回と同じく Phew さん出演。

こちらは DMX を駆使する PowWow インドネシアの Bagus Pandega さん。DMX Box を使っていただきました。




とまあ、2日展示をやると体力は消耗しましたけど、なかなか興味深いものが見れました。
そして今週末もイベント続きで 24日(土) シンセビルダーズサミット@科学技術館、25(日) HTML5Conference@東京電機大がありますので、参加される方はまた会場で。

Posted by g200kg : 10:40 AM : PermaLink

2018/11/20 (2018年11月 のアーカイブ)

InterBEEとかWebAudio.tokyoとか

Twitter Google+ Facebook

この時期、各種イベントが集中しています。とりあえず先週分です。

11月15日、幕張メッセで InterBEE が開催されました。InterBEEは 今まであまり見に行ってなかったのだけど、今回はたまたま近所に用事ができたりで覗いてきました。

入口の看板はこんな感じ。

基本的に放送機器関連なので tc electronic もラウドネスメーターとかをプッシュしています。

これも tc electronic。ビンテージデジタルリバーブを再現するプラグインと専用のインターフェース。ハードウェアがソフトウェアになって、更に一部をハードウェアに戻した感じ。そういう流れはあるかもな。

Cubase 10 が出たばかりだけど、ヤマハも InterBEE では Cubase じゃなくて Nuendo なんだね。

ヤマハブースでやっていたセミナー。Dante が凄くプッシュされている感じがする。ここ数年でもうみんな Dante でネットワーク化しようぜっていう圧力が高まったようです。

こちらはハイエンドオーディオI/FのAntelope Audio。ギタリスト ichika さんのデモ。

MI7ブースでは音楽制作系でお馴染みの Softube や Zynaptiq の展示。

最近ちょっと照明系も気になったりするのだけど、流石に InterBEE に展示されているのはでかくて個人でどうこうするようなものではない。

照明系でちょっと目をひいたレーザーを少し拡散する感じの拡散ビーム砲的な奴。面白そうだけどこういうのはフォグ併用が前提だろうな。

これは同時開催の DCExpo の方だったかな。黒柳徹子アンドロイドが新AI を搭載して自律応答するようになったらしいです。AI がメディアを征服するまで頑張ってほしい。

内容はチェックしてませんが VTuber ハッカソンなるイベントも行われていたようです。


さて、そして11月15日夕方からは目黒で WebAudio.tokyo の LT大会 #6 です。

会場は目黒のアルコタワー Drecom 様です。

演目はこんな感じ。W3C TPAC AudioWG の報告や密かに局所的なブームになっているかも知れない演奏情報のABCノーテーションの話など。私からは WebAudioAPI CR 版について少し話しました。

こちらは飛び込み LT で紹介された 楽譜 IME 的な奴。なかなか興味深かったです。これは今週末に北千住で開催される HTML5カンファレンスの展示にも持ってきてくれる事になりましたので是非。


さて、そして先週末 17日、18日は渋谷 Contact で モジュラーフェスティバル TFoM が開催され、更に今週末は 24日シンセビルダーズサミット@科学技術館、25日は HTML5カンファレンス@北千住、東京電機大があります。

なんかうまい事週末が隙間なく埋まってしまって体力的に厳しい。

Posted by g200kg : 5:11 AM : PermaLink



...更に以前の記事...


g200kg