JSFXプログラミングリファレンス - 言語の基本

原文 http://www.reaper.fm/sdk/js/basiccode.php

## 基本的なコードリファレンス

JSFXのコアになるのはEEL2と呼ばれる単純なプログラミング言語で書かれたコードで、C言語に似ています。コードは一つまたは複数の**コードセクション**に書かれます。この言語のいくつかの基本的な機能は以下のとおりです:

* 変数は宣言される必要がありません。デフォルトでエフェクト内でグローバルにアクセスできます。そして全ては倍精度浮動小数点数です。
* 加算(+)、減算(-)、乗算(*)、除算(/)指数(^)の基本的な演算ができます。
* 和集合(|)、積集合(&)、排他的論理和(~)、左シフト(<<)、符号拡張右シフト(>>)のビット演算ができます。これらは計算時に整数に変換されます。
* "(" と ")" のかっこは計算順を指定したり、関数の引数を指定したり、複数のステートメントを一つのステートメントとしてまとめたりするのに使われます。
* セミコロン`;`はステートメントを分けるために使われます。
* 仮想ローカル変数空間は約800万ワード存在し、これは "[" と "]"のかっこでアクセスできます。
* 共有グローバル変数空間は約100万ワード存在し、`gmem[]`でアクセスできます。これは全てのJSFXプラグインインスタンスで共有されます。
* 名前付き共有グローバル変数は"_global."プリフィックスを付けることでアクセスできます。これは全てのJSFXプラグインインスタンスで共有されます。
* ユーザー定義関数はプライベート変数、パラメーターを定義することができ、名前空間付きインスタンス変数にアクセスすることも可能です。
* 数値は通常10進数ですが、`$x` でプリフィックスすると16進数になります。(`$x90`, `$xDEADBEEF`, 等). -- (REAPER v4.25以上ではC言語風の`0x90`のような指定も可能です)
* ASCII文字列は`$'c'`で指定可能です。
* 整数のビットマスクを指定したい場合は`$~X`を使います。たとえば`$~7`は127、`$~8`は255、`$~16`は65535を表します。-- REAPER 4.25以上
* コメントはこれらを使います:

```js
// 行末までコメント
/* 複数行にまたがることのできるコメント */
```

## 演算子リファレンス

最も高い優先度から低い優先度の順に並べます。(しかしかっこを使う場合はこの限りではありません!):

### [ ]

```js
z=x[y]; 
x[y]=z;
```

かっこはエフェクト内のローカルメモリのインデックスとして使われます。エフェクト内には約800万(8,388,608)スロットのメモリがあり、固定のオフセット(i.e. 16811[0])もしくは変数名(myBuffer[5])でアクセスできます。かっこの左側にある値とかっこの中にある値の和がメモリのインデックスになります。かっこの中の値が省略された場合は、かっこの左側にある値が使われます。

```js
z=gmem[y]; 
gmem[y]=z;
```

`gmem`がかっこの左側に指定された場合、グローバル共有メモリが使用されます。これは約100万(1,048,576)スロットのメモリがあり、全てのJSFXエフェクトのインスタンスで共有されます。

プラグインは次のようにすることもできます。(**コードセクション**の前で):

```js
options:gmem=someUniquelyNamedSpace
```

これは`gmem[]`より大きな共有バッファで、`options:gmem=<the same name>`を使うことで他のプラグインからアクセスできるようになります。もしいくつかのプラグインが同時に動作する場合、共有メモリを使うことで他のプラグインを気にすることなくコミュニケーションすることができます。このオプションは`gmem[]`の大きさを800万エントリーに拡大させます。(デフォルトは約100万) -- REAPER 4.6以上

### !value

論理的NOT演算の結果を返します。(もし元の値が0.0なら、1.0を返します。そうでなければ0.0を返します。)

### -value

符号反転させた値を返します。(-1 * value)

### +value

変更されていない値を返します。

### a ^ b

`a`の`b`乗の結果を返します。`pow(a,b)`関数を使うのと同じです。

### numerator % denominator

整数として除算を行い、その余りを返します。

### value << shift_amt

双方の値を32ビット整数に変換し、2番目のパラメーターの分だけ左方向へのビットシフト演算をします。32より大きな数や0より小さい数でビットシフトすると不定の結果を返します。-- REAPER 4.111以上

### value >> shift_amt

双方の値を32ビット整数に変換し、2番目のパラメーターの分だけ右方向へのビットシフト演算をします。符号ビットは元の値のものを引き継ぎます(`y`が負の数なら、結果は正にならない)。32より大きな数や0より小さい数でビットシフトすると不定の結果を返します。-- REAPER 4.111以上

### value / divisor

二つの値の除算の結果を返します。

### value * another_value

二つの値の乗算の結果を返します。

### value - another_value

二つの値の差を返します。

### value + another_value

二つの値の和を返します。

### a | b -- 二つの値を32ビット整数に変換し、ビットごとの論理和を計算して返します。
### a & b -- 二つの値を32ビット整数に変換し、ビットごとの論理積を計算して返します。
### a ~ b -- 二つの値を32ビット整数に変換し、ビットごとの排他的論理和を計算して返します。-- REAPER 4.25以上

### value1 == value2 -- 二つの値を比べて、差が0.00001未満なら1を、そうでなければ0を返します。
### value1 === value2 -- 二つの値を比べて、確実に等しいなら1を、そうでなければ0を返します。-- REAPER 4.53以上
### value1 != value2 -- 二つの値を比べて、差が0.00001未満なら0を、そうでなければ1を返します。
### value1 !== value2 -- 二つの値を比べて、確実に等しいなら0を、そうでなければ1を返します。-- REAPER 4.53以上
### value1 < value2 -- 二つの値を比べて、最初のパラメーターが次のパラメーターより小さいなら1を返します。
### value1 > value2 -- 二つの値を比べて、最初のパラメーターが次のパラメーターより大きいなら1を返します。
### value1 <= value2 -- 二つの値を比べて、最初のパラメーターが次のパラメーター以下なら1を返します。
### value1 >= value2 -- 二つの値を比べて、最初のパラメーターが次のパラメーター以上なら1を返します。

### y || z -- 二つの値の論理和を返します。もし`y`が0でないなら、`z`は評価されません。
### y && z -- 二つの値の論理積を返します。もし`y`が0なら、`z`は評価されません。

### y ? z

`y`が0でなければ、`z`を評価します。C言語の`if (y) { z }`のようなものです。

### y ? z : x

`y`が0でなければ`z`を評価し、そうでなければ`x`を評価します。C言語の`if (y) { z } else { x }`のようなものです。

`z`,`x`にあたる部分はかっこを使うことで複数のステートメントを含むことができます。

```js
x % 5 ? (
  f += 1;
  x *= 1.5;
) : (
  f = max(3, f);
  x = 0;
);
```

### y = z

`z`の値を`y`に代入します。`z`は変数か、式です。

### y *= z

二つの乗算を行い、結果を`y`に格納します。

### y /= divisor

除算を行い、結果を`y`に格納します。

### y %= divisor

整数として除算を行い、余りを`y`に格納します。

### a ^= b

`a`の`b`乗を計算して、結果を`a`に格納します。

### y += z

二つの結果を加算して、結果を`y`に格納します。

### y -= z

`y-z`の減算を行い、結果を`y`に格納します。

### y |= z

双方を整数に変換して、ビットごとの論理和を計算して、結果を`y`に格納します。

### y &= z

双方を整数に変換して、ビットごとの論理積を計算して、結果を`y`に格納します。

### y ~= z

双方を整数に変換して、ビットごとの排他的論理和を計算して、結果を`y`に格納します。-- REAPER 4.25以上

特にC言語のプログラマーは以下の点に気をつけましょう。

### ( )

`(`,`)`は複数のステートメントを囲み、最後の式の値が評価されます。

```js:例
z = (
  a = 5; 
  b = 3; 
  a + b;
); // z は8になる。
```

### 条件分岐

条件分岐は`if() else`ではなく`?`または`? :`を使って作ります。

```js:例
a < 5 ? b = 6;         // aが5未満なら、bに6を代入する
a < 5 ? b = 6 : c = 7; // aが5未満なら、bに6を代入、そうでなければcに7を代入する。
a < 5 ? (              // aが5未満なら、bに6を代入して、cに7を代入する。
  b = 6;
  c = 7;
);
```

`?`,`?:`のオペレーターは、式の左辺にも使うことができます。

```js
(a < 5 ? b : c) = 8; // もしaが5未満なら、bに8を代入、そうでなければcに8を代入する。
```

## 単純な数学関数

* sin(angle) -- 指定した角度のサインを返します。指定する角度の単位はラジアンです。度からラジアンに変換するためには、`$pi/180`もしくは`0.017453`をかけてください。
* cos(angle) -- コサインを返します。指定する角度の単位はラジアンです。
* tan(angle) -- タンジェントを返します。指定する角度の単位はラジアンです。
* asin(x) -- アークサインを返します。単位はラジアンです。
* acos(x) -- アークコサインを返します。単位はラジアンです。
* atan(x) -- アークタンジェントを返します。単位はラジアンです。
* atan2(x,y) -- $atan(\frac{x}{y})$を返します。単位はラジアンです。
* sqr(x) -- 二乗を返します(`x * x`と似ていますが、`x`は一度しか評価されません)。
* sqrt(x) -- 平方根を返します。
* pow(x,y) -- `x`の`y`乗を返します。動作とパフォーマンスは`^`演算子と同じです。
* exp(x) -- $e$ (約2.718)の`x`乗を返します。この関数は`pow()`や`^`演算子を使うよりもとても高速です。
* log(x) -- $e$を底とする自然対数を返します。
* log10(x) -- 10を底とする自然対数を返します。
* abs(x) -- 絶対値を返します。
* min(x,y) -- 二つの引数の最小値を返します。
* max(x,y) -- 二つの引数の最大値を返します。
* sign(x) -- 引数の符号を返します(-1, 0, 1のいずれか)。
* rand(x) -- 0以上x未満の擬似乱数を返します。
* floor(x) -- x以下で最も大きい整数を返します (floor(3.9)==3, floor(-3.1)==-4)。
* ceil(x) -- x以上で最も小さい整数を返します (ceil(3.1)==4, ceil(-3.9)==-3)。
* invsqrt(x) -- 平方根の逆数($\frac{1}{\sqrt{x}}$)を高速に計算します

## ループ

JSFXでのループは以下の関数で作成します。

### loop( 回数, コード)

```js
loop(32, 
  r += b;
  b = var * 1.5;
);
```

最初の引数がループの回数を決定します。この引数が1未満なら、第二引数は評価されません。
最初の引数に大きすぎる値を指定しないように気をつけましょう。もしそうするとエフェクトが長時間のフリーズを引き起こします。実行時のフリーズを避けるため、繰り返し回数は約1,000,000回に制限されています。もしもっとたくさんのループが必要だとしたら、設計を考え直した方が良いでしょう(もしくは最後の手段としてループをネストしてください)。

最初の引数は一度しか評価されません(なのでループの中で変数を変更しても、ループ回数は変わりません)。回数の不明なループを作りたい場合は、次の`while()`を見てください。

### while( コード )

```js
while(
  a += b;
  b *= 1.5;
  a < 1000; // aが1000未満の間繰り返し
);
```

最初のパラメーターの最後のステートメントが0と評価されるまで繰り返します。

実行時のフリーズを避けるため、繰り返し回数は約1,000,000回に制限されています。もしもっとたくさんのループが必要だとしたら、設計を考え直した方が良いでしょう(もしくは最後の手段としてループをネストしてください)。

### while( 条件 ) ( コード ) -- REAPER 4.59以上

```js
while ( a < 1000 ) (
  a += b;
  b *= 1.5;
);
```

引数を評価して、0でなければ後続するコードブロックを実行し、繰り返します。これはC言語の`while()`と似ています。

実行時のフリーズを避けるため、繰り返し回数は約1,000,000回に制限されています。もしもっとたくさんのループが必要だとしたら、設計を考え直した方が良いでしょう(もしくは最後の手段としてループをネストしてください)。

## 時間の関数

### time([v]) -- REAPER 4.60+

現在時刻を1970年1月1日からの秒数で返します。引数が与えられると、その引数にタイムスタンプが設定されます。

### time_precise([v]) -- REAPER 4.60+

システム固有のタイムスタンプを返します。精度はシステムにより異なりますが、大抵は1ミリ秒未満です。ベンチマークに便利です。引数が指定された場合は、その引数にタイムスタンプが設定されます。