ROLI BLOCKSでLittleFootを使うはじめ

#はじめに

ROLI BLocksで光らせたりするのととりあえず試すために

Blocks Codeを手に入れる
https://juce.com/blocks/code

# インストールして起動

![image.png](https://qiita-image-store.s3.amazonaws.com/0/96808/382b56a9-4887-a84c-27fd-6be3aaa1bed5.png)

# ROLI Blocksを繋ぐ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/96808/bf03fe5b-dbdd-0789-433e-ad6b656cac8c.png)

Lightpad Blockが認識されているのを確認

# 試す

ファイルメニューからNewFile

![image.png](https://qiita-image-store.s3.amazonaws.com/0/96808/cb1bc3a4-3381-321d-9b0d-89b5eeac096a.png)

ファイルができる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/96808/6e233433-4bba-c41a-7d2c-192e010418bb.png)

# コードを入力

AkiyukiOkayasuさんのGitHubから
https://github.com/AkiyukiOkayasu/BLOCKS_Etude

AkiyukiOkayasu/BLOCKS_Etude

https://github.com/AkiyukiOkayasu/BLOCKS_Etude/blob/master/Lightpad%20Block/XYZ%20Pad/XYZPad.littlefoot

をペーストします

![IMG_5310.JPG](https://qiita-image-store.s3.amazonaws.com/0/96808/4c4e5058-78a1-61f9-3a86-570b0e7fe3e3.jpeg)

これだけで、うまくいっていれば、Blocksが光ります

# 情報源

リンク集

関数リファレンス的な
https://docs.juce.com/master/group__LittleFootFunctions.html

The BLOCKS SDK
https://docs.juce.com/blocks/downloading_the_sdk.html


LittleFoot Example
https://docs.juce.com/blocks/example_scripts.html

LittleFootの言語仕様
https://github.com/WeAreROLI/JUCE/blob/master/modules/juce_blocks_basics/littlefoot/LittleFoot%20Language%20README.txt

sinとか　自作が必要
tjsurumeさんonomutaさん　（TokyoBlocksHackathon2017のじゃんけんのコード）
にmy_sinがある
https://github.com/onomuta/tbh2017/blob/master/blockBattle.littlefoot



#　タッチしたら赤く光る

とりあえず、光らせるとアガるので。
眠らせているBLOCKSに命が入る。

```
void touchStart (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFFFFFF, x, y, z * 10.0);
}

void touchMove (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFF0000, x, y, z * 10.0);
}

void touchEnd (int touchIndex, float x, float y, float z, float vz)
{
}

void repaint()
{
    clearDisplay();
    drawPressureMap();
    fadePressureMap();    
}
```

# 何か押したところが綺麗に光るもの

```
void touchStart (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFFFFFF, x, y, z * 10.0);
}

void touchMove (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFF0000, x-0.1, y, z * 2.0);
    addPressurePoint (0xFF00FF00, x, y+0.1, z * 5.0);
    addPressurePoint (0xFF0000BB, x+0.1, y, z * 10.0);
}

void touchEnd (int touchIndex, float x, float y, float z, float vz)
{
}

void repaint()
{
    clearDisplay();
    drawPressureMap();
    fadePressureMap();    
}
```
![IMG_5311.gif](https://qiita-image-store.s3.amazonaws.com/0/96808/bafa3c72-3f95-2823-4210-4110a2c91e6e.gif)

# VJソフトのパラメータを動かしてみる

押し込みとかで少しズームするのはありかも

と思いつつ、座標XY ズームをZで操作。

AkiyukiOkayasuさんのコードをお借りしつつ

```
/*
<metadata description="Minimal XYZ Pad" details="XY pad with the addition of pressure (Z), sending out MIDI CC. You can set MIDI channel."
          target="Lightpad" 
          tags="MIDI;Controller;">
    <variables>
        <variable name="channel" displayName="MIDI Channel" type="int" min="1" max="16" value="1" displayMode="stepper" tooltip="The MIDI channel that values are sent on" />
    </variables>
</metadata>
*/

int ccX;
int ccY;
int ccZ;

void touchStart (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFFFFFF, x, y, z * 10.0);
}

void touchMove (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFF0000, x-0.1, y, z * 2.0);
    addPressurePoint (0xFF00FF00, x, y+0.1, z * 5.0);
    addPressurePoint (0xFF0000BB, x+0.1, y, z * 10.0);
    
    ccX = int(map(x, 0.07, 1.93, 0.0, 127.0));//X座標のデータ(0.07~1.93)を0~127に変換
    ccY = int(map(y, 0.07, 1.93, 0.0, 127.0));//Y座標のデータ(0.07~1.93)を0~127に変換
    ccZ = int(map(z, 0.0, 1.0, 0.0, 127.0));//Z(プレッシャー)のデータを(0.0~1.0)を0~127に変換
    sendCC ((channel - 1), 60, ccX);//X座標 CC60
    sendCC ((channel - 1), 61, ccY);//Y座標 CC61
    sendCC ((channel - 1), 62, ccZ);//プレッシャー  CC62
}

void touchEnd (int touchIndex, float x, float y, float z, float vz)
{
}

void repaint()
{
    clearDisplay();
    drawPressureMap();
    fadePressureMap();    
}
```

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ResolumeのパラメータもMIDI経由で動かせた <a href="https://t.co/ptWIDkSAfU">pic.twitter.com/ptWIDkSAfU</a></p>&mdash; tatmos (@tatmos) <a href="https://twitter.com/tatmos/status/1056062124928069632?ref_src=twsrc%5Etfw">2018年10月27日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


 Resolume側の設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/96808/b9589223-8709-b9dd-975a-410388f44624.png)

### 実際やってみて
・・・　Resloumeとの連携をMIDIでいじるということは、
clipの選択とかがResolumeで選ばないといけないとか、　
clip切り替えを別デバイス（LaunchPadとか）にしたとしても、切り替え時の設定リセットとか、
ちょっと工夫が必要そう・・・間にMaxとか挟まないとかなぁという感じ。
OSC経由にしても、clip切り替え時のリセットがちょっと煩雑になるなぁなど。

# タッチした周辺をゆらゆら色が動くような

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">マルチタッチ <br>タッチした周辺を揺ら揺ら色が動く <a href="https://t.co/ER1K0WFszA">pic.twitter.com/ER1K0WFszA</a></p>&mdash; tatmos (@tatmos) <a href="https://twitter.com/tatmos/status/1056080930459181056?ref_src=twsrc%5Etfw">2018年10月27日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


```
/*
<metadata description="Minimal XYZ Pad" details="XY pad with the addition of pressure (Z), sending out MIDI CC. You can set MIDI channel."
          target="Lightpad" 
          tags="MIDI;Controller;">
    <variables>
        <variable name="channel" displayName="MIDI Channel" type="int" min="1" max="16" value="1" displayMode="stepper" tooltip="The MIDI channel that values are sent on" />
    </variables>
</metadata>
*/

int ccX;
int ccY;
int ccZ;
int counter;

float pi;

void initialise()
{
    pi = 3.141592;
    counter = 0;
}

float my_sin(float x){
    
    int nMAX = 10;
    x -= (int(x / (2 * pi)) * 2 * pi);
  
    float sum = x;// 合計値
    float t = x;
 
    for(int n=1;n<=nMAX;n++){
        t *= - (x * x) / ((2 * n + 1) * (2 * n));
        sum += t;
    }

    sum = (sum + 1)/2;    
    return sum;
}

void touchStart (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFFFFFF, x, y, z * 10.0);
}

void touchMove (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFF0000, x+my_sin(counter*0.3)*0.75-0.25, y, z * 20.0);
    addPressurePoint (0xFF00FF00, x, y+my_sin(counter*0.2)*0.5-0.25, z * 50.0);
    addPressurePoint (0xFF0000BB, x+my_sin(counter*0.1)*0.75-0.25, y, z * 10.0);
    
    ccX = int(map(x, 0.07, 1.93, 0.0, 127.0));//X座標のデータ(0.07~1.93)を0~127に変換
    ccY = int(map(y, 0.07, 1.93, 0.0, 127.0));//Y座標のデータ(0.07~1.93)を0~127に変換
    ccZ = int(map(z, 0.0, 1.0, 0.0, 127.0));//Z(プレッシャー)のデータを(0.0~1.0)を0~127に変換
    sendCC ((channel - 1), 60, ccX);//X座標 CC60
    sendCC ((channel - 1), 61, ccY);//Y座標 CC61
    sendCC ((channel - 1), 62, ccZ);//プレッシャー  CC62
}

void touchEnd (int touchIndex, float x, float y, float z, float vz)
{
}

void repaint()
{
   clearDisplay();
   drawPressureMap();
   fadePressureMap();    
   counter++;
}

```


# タッチIndexで動きをばらつかせる

指ごとにすこし周期をずらしてより複雑な感じに

```
/*
<metadata description="Minimal XYZ Pad" details="XY pad with the addition of pressure (Z), sending out MIDI CC. You can set MIDI channel."
          target="Lightpad" 
          tags="MIDI;Controller;">
    <variables>
        <variable name="channel" displayName="MIDI Channel" type="int" min="1" max="16" value="1" displayMode="stepper" tooltip="The MIDI channel that values are sent on" />
    </variables>
</metadata>
*/

int ccX;
int ccY;
int ccZ;
int counter;

float pi;

void initialise()
{
    pi = 3.141592;
    counter = 0;
}

float my_sin(float x){
    
    int nMAX = 10;
    x -= (int(x / (2 * pi)) * 2 * pi);
  
    float sum = x;// 合計値
    float t = x;
 
    for(int n=1;n<=nMAX;n++){
        t *= - (x * x) / ((2 * n + 1) * (2 * n));
        sum += t;
    }

    sum = (sum + 1)/2;    
    return sum;
}

void touchStart (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFFFFFF, x, y, z * 10.0);
}

void touchMove (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFF0000, x+my_sin((counter+index*5)*0.3)*0.75-0.25, y, z * 20.0);
    addPressurePoint (0xFF00FF00, x, y+my_sin((counter+index*12)*0.2)*0.5-0.25, z * 50.0);
    addPressurePoint (0xFF0000BB, x+my_sin((counter+index*10)*0.1)*0.75-0.25, y, z * 10.0);
    
    ccX = int(map(x, 0.07, 1.93, 0.0, 127.0));//X座標のデータ(0.07~1.93)を0~127に変換
    ccY = int(map(y, 0.07, 1.93, 0.0, 127.0));//Y座標のデータ(0.07~1.93)を0~127に変換
    ccZ = int(map(z, 0.0, 1.0, 0.0, 127.0));//Z(プレッシャー)のデータを(0.0~1.0)を0~127に変換
    sendCC ((channel - 1), 60, ccX);//X座標 CC60
    sendCC ((channel - 1), 61, ccY);//Y座標 CC61
    sendCC ((channel - 1), 62, ccZ);//プレッシャー  CC62
}

void touchEnd (int touchIndex, float x, float y, float z, float vz)
{
}

void repaint()
{
   clearDisplay();
   drawPressureMap();
   fadePressureMap();    
   counter++;
}
```

# ランダムに自動でタッチする

押していなくても
repaintで、たまに勝手に発火するような。線香花火のような表示。

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">ランダムに表示する  <a href="https://twitter.com/hashtag/ROLIBLOCKS?src=hash&amp;ref_src=twsrc%5Etfw">#ROLIBLOCKS</a> <a href="https://twitter.com/hashtag/JUCE?src=hash&amp;ref_src=twsrc%5Etfw">#JUCE</a> <a href="https://t.co/zOQv9iGKlV">pic.twitter.com/zOQv9iGKlV</a></p>&mdash; tatmos (@tatmos) <a href="https://twitter.com/tatmos/status/1056096939039551488?ref_src=twsrc%5Etfw">2018年10月27日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


```
/*
<metadata description="Minimal XYZ Pad" details="XY pad with the addition of pressure (Z), sending out MIDI CC. You can set MIDI channel."
          target="Lightpad" 
          tags="MIDI;Controller;">
    <variables>
        <variable name="channel" displayName="MIDI Channel" type="int" min="1" max="16" value="1" displayMode="stepper" tooltip="The MIDI channel that values are sent on" />
    </variables>
</metadata>
*/

int ccX;
int ccY;
int ccZ;
int counter;

float pi;

void initialise()
{
    pi = 3.141592;
    counter = 0;
}

float my_sin(float x){
    
    int nMAX = 10;
    x -= (int(x / (2 * pi)) * 2 * pi);
  
    float sum = x;// 合計値
    float t = x;
 
    for(int n=1;n<=nMAX;n++){
        t *= - (x * x) / ((2 * n + 1) * (2 * n));
        sum += t;
    }

    sum = (sum + 1)/2;    
    return sum;
}

void touchStart (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFFFFFF, x, y, z * 10.0);
}

void touchMove (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFF0000, x+my_sin((counter+index*5)*0.3)*0.75-0.25, y, z * 20.0);
    addPressurePoint (0xFF00FF00, x, y+my_sin((counter+index*12)*0.2)*0.5-0.25, z * 50.0);
    addPressurePoint (0xFF0000BB, x+my_sin((counter+index*10)*0.1)*0.75-0.25, y, z * 10.0);
    
    ccX = int(map(x, 0.07, 1.93, 0.0, 127.0));//X座標のデータ(0.07~1.93)を0~127に変換
    ccY = int(map(y, 0.07, 1.93, 0.0, 127.0));//Y座標のデータ(0.07~1.93)を0~127に変換
    ccZ = int(map(z, 0.0, 1.0, 0.0, 127.0));//Z(プレッシャー)のデータを(0.0~1.0)を0~127に変換
    sendCC ((channel - 1), 60, ccX);//X座標 CC60
    sendCC ((channel - 1), 61, ccY);//Y座標 CC61
    sendCC ((channel - 1), 62, ccZ);//プレッシャー  CC62
}

void touchEnd (int touchIndex, float x, float y, float z, float vz)
{
}

void repaint()
{
   if(getRandomInt(5) == 0)
    {
        float x = getRandomFloat()+0.5;
        float y = getRandomFloat()+0.5;
        float z = getRandomFloat()+0.5;
        
        int index = 0;
        
        addPressurePoint (0xFFFF0000, x+my_sin((counter+index*5)*0.3)*0.75-0.25, y, z * 20.0);
        addPressurePoint (0xFF00FF00, x, y+my_sin((counter+index*12)*0.2)*0.5-0.25, z * 50.0);
        addPressurePoint (0xFF0000BB, x+my_sin((counter+index*10)*0.1)*0.75-0.25, y, z * 10.0);
    }
    
    
   clearDisplay();
   drawPressureMap();
   fadePressureMap();    
   counter++;
}

```




# アイデア

ここまでやってみて
- blutoothで接続して、クリックしたらMax経由でNode.jsでAmazonに注文　とかできそう。
- スタンドアローンにならないので、ホストのminiPCみたいなのをBlocksの裏側にはりつけとくとか。
- タップすると「いいね」が出せるとか。
- 大きめの「お気に入り」ボタン　とか。

アイコン付きのボタンとしての用途が思いつく。

- メガデモ　を作るのもありかも　（littlefootメモリ容量は8KBくらいの様子）

# littlefootで作ると良い点

blocksの中で処理するので 反応が良い

メモリが限られているので あまり複雑なことはできない

ホストが繋がっていないといけない
USBかBluetoothで

スタンドアローンの押して光るデバイスではないのか 要調査

言語がシンプル＆コンパイルが早い ライブコーディング的
Processing 
GLSL っぽい感じ







# おわりに

今回は[JUCEもくもく会](https://juce.connpass.com/event/104732/)で得られた知見でした。
ここから始められそうです。
いろいろ作ってみよう。