2015年6月29日 星期一

Creating a wireless MIDI connection between computers

since: 2015/06/29
update: 2015/06/29

reference:
1. Mac OS:Creating a wireless MIDI connection between computers
2. How to send Midi via Wifi on Mac - Tutorial on Vimeo

A. 功能定義:
     1. Master (主控)端:
         利用 Processing 程式, 將 MIDI 訊號藉由( 程式 / Ableton Live) 輸出給 Slave 端.

     2. Slave (隨從)端:
         輸入(接受) Master 端送來的 MIDI 訊號, 播放對應的音軌效果.

-----------------------------------------------------------------------------------------------

B. MIDI 網路設定:
    1. Master 端:
        a. 工具程式 > 音訊 MIDI 設定:

        b. 視窗 > 顯示 MIDI 錄音室
             > 雙擊 "網路"

        c. > 在左上方,  "我的區段", 按下 "+" 新增一個區段.
            > 於右上方, 勾選 "已啟用", 並將 "本機名稱" 與 "Bonjour 名稱" 設為:
                Wireless MIDI Master

            > 在左下方, 將 "可能連接本機的有": 設為 "所有參與者"

    2. Slave 端:
        類似 Master 的方式:
        > 在左上方,  "我的區段", 按下 "+" 新增一個區段.
        > 於右上方, 勾選 "已啟用", 並將 "本機名稱" 與 "Bonjour 名稱" 設為:
           Wireless MIDI Slave

        > 在左下方, 將 "可能連接本機的有": 設為 "所有參與者"

    3. 建立 Master 與 Slave 區段的連結:
        a. 於 Master 端:
            先點選 "Wireless MIDI Master" 區段,
            再點選目錄內的 "Wireless MIDI Slave",
            按下 "連線" 後, 可於右方的 "參與者" 看到 "Wireless MIDI Slave"

        b. 於 Slave 端:
            先點選 "Wireless MIDI Slave" 區段,
            再點選目錄內的 "Wireless MIDI Master",
            按下 "連線" 後, 可於右方的 "參與者" 看到 "Wireless MIDI Master"

-----------------------------------------------------------------------------------------------

C. Ableton Live 偏好設定:
    1. Master 端:
        將 Wireless MIDI Master 網路輸出的 Track, Sync, Remote 皆設成 On. 

        備註: 由於在此例 MIDI 訊號是由 Processing 程式送出, 因此關閉 Ableton Live ,
                  也可正常運作, 亦即不需要設定 Ableton Live (尚未驗證).

    2. Slave 端:
        將 Wireless MIDI Master 網路輸入的 Track, Sync, Remote 皆設成 On.

-----------------------------------------------------------------------------------------------

D. 音軌 Mapping:
     Slave 端:
     1. 拖拉一個 Drum Rack 到下方, 確認按鍵與位置的對應, 在此為:
          "A 鍵" 對應到 "C5" 位置.

     2. 將一個音效拖拉到剛剛 "C5" 的位置, 並按下 "A 鍵", 來確認是否有聽到聲音播放.

-----------------------------------------------------------------------------------------------

E. Processing 程式:
    1. MIDI Note Numbers Mappings

    說明: 由上表可查得 C5 對應到 Note Number 為: 84
    2. Master 端:
        開啟 Processing 轉寫程式如下:

import themidibus.*; //Import the MIDI library

MidiBus myBus; // The MidiBus

void setup() {
  size(400, 400);
  background(0);

  MidiBus.list();
  // Create a new MidiBus with no input device
  // and the "Wireless MIDI Master" as output device.

  myBus = new MidiBus(this, -1, "Wireless MIDI Master");
}

void draw() {
  int channel = 0; // 頻道: 0 ~ 15
  int pitch = 84; // 音調
  int velocity = 127; // 速度

  Note note = new Note(channel, pitch, velocity);
  myBus.sendNoteOn(note);
  delay(2000);
 
  myBus.sendNoteOff(note);

  int number = 0;
  int value = 120;
  ControlChange change = new ControlChange(channel, number, value);
  myBus.sendControllerChange(change); // Send a controllerChange
  delay(1000);
}

void delay(int time) {
  int current = millis();
  while (millis () < current+time) Thread.yield();
}



2015年6月26日 星期五

Processing: MIDI Mappings To Ableton Live With The MidiBus

since: 2015/06/26
update: 2015/06/26

reference:
1. Small But Digital - The MidiBus
2. snoize: MIDI Monitor

A. Create a virtual MIDI Port:
    1. 應用程式 > 工具程式 > 音訊 MIDI 設定.app


   2. 視窗 > 顯示 MIDI 錄音室

   3. 滑鼠雙擊 IAC (Inter-application communication) 驅動程式:

    4. 勾選: 裝置已接上電腦; 新增自訂名稱的傳輸埠, 即完成.

-----------------------------------------------------------------------------------------------


B. Setup
virtual MIDI Port on Processing:
 
     說明: 我們的目的是要從 Processing 發送 MIDI 訊號給 Ableton Live 接收,
               1. 程式本身不需要輸入 MIDI 訊號, 因而將 Input Device 設成 -1.
               2. 而將 MIDI 訊號 Output 到剛剛新增的 virtual MIDI Port: "IAC_MIDI"

-----------------------------------------------------------------------------------------------

C. Setup virtual MIDI Port on Ableton Live: 
     說明:
     1. Ableton Live > Preferences > MIDI Sync
     2. 將 Processing 用來 Output MIDI 訊號的 virtual MIDI Port: "IAC_MIDI",
         設定成 Ableton Live 的 Input MIDI Port, 並且將其 Track 與 Remote 設成 On.

-----------------------------------------------------------------------------------------------

D. 製作音軌資料, 並將上方的量化選單(Quantization Menu)設成:
     None (不使用節拍)


-----------------------------------------------------------------------------------------------

E. Processing 擊鼓模擬:  
     ---> 發送 ControllerChange 訊號給 Ableton Live

    固定值:
    int channel = 0; // 頻道: 0 ~ 15
    int controllerValue = 127;

    調整值:
    int controllerNumber = 0;  // 0, 1, 2, 3 .....


-----------------------------------------------------------------------------------------------

F. Ableton Live: MIDI Mappings
    1. 按下 Ableton Live 右上方的 "MIDI", 切換到 MIDI Map 模式.
    2. 每次點取不同的音軌, 接著執行 Processing 程式發送出 ControllerChange 訊號.
    3. Ableton Live 會自動將所接收到的 ControllerChange 訊號,
        與所點取的 音軌 作Mapping.   

2015年6月14日 星期日

AppleScript: Checking memory every 30 sec. If it is about to out of memory then restart OS

since: 2015/06/14
update: 2015/06/14


A. 撰寫 Applescript:
    1. 開啟 Automator:

   
     2. Automator > 檔案 > 新增 > 應用程式 > 選擇:
    
     3. 工具程式 > 執行 AppleScript > 拖拉到右方

    4. 預設程式碼:
on run {input, parameters}
   
    (* Your script goes here *)
   
    return input
end run




    5. 修改如下:
on run {input, parameters}
   
    repeat
       

        # query memory free (MB)
        set vmStats to (text 12 thru -2 of (do shell script "vm_stat | grep 'Pages free'")) * 4096 / 1024 / 1024
        

        # if vmStats <= 500 MB
        if vmStats <= 500 then
       
            # show
dialog message (for debug used)           
            #display dialog vmStats with title "
Memory Free (MB)" buttons {"OK"} default button 1
           
            #
kill your app   
            tell application "System Events"
                set ProcessList to name of every process
                    #
"my_app" is your app name                   
                    if "my_app" is in ProcessList then
                        set ThePID to unix id of process "my_app"
                        # kill
"my_app" process                      
                        do shell script "kill -KILL " & ThePID
                    end if
            end tell
   
            # restart the OS
            tell application "Finder"
                restart
            end tell
   
        end if
       
        #
delay 30 second       
        delay 30
       
    end repeat

   
    return input
end run

2015年6月10日 星期三

Processing: Get Free Memory Info With AppleScript

since: 2015/06/10
update: 2015/06/10

reference:
1. Troubleshooting · processing/processing Wiki

2. Applescript show free memory | Apple Support Communities
3. AppleScript: Essential Sub-Routines
4. io - How do I write to a text file using AppleScript? - Stack Overflow

A. 撰寫 Applescript:
    1. 開啟 Automator:

   
     2. Automator > 檔案 > 新增 > 應用程式 > 選擇:
    
     3. 工具程式 > 執行 AppleScript > 拖拉到右方

    4. 預設程式碼:
on run {input, parameters}
   
    (* Your script goes here *)
   
    return input
end run




    5. 修改如下:
on run {input, parameters}
   
   
    # get the number of free pages using 'vm_stat' and multiply by the page size
    set vmStats to (text 12 thru -2 of (do shell script "vm_stat | grep 'Pages free'")) * 4096
    # display dialog vmStats with title "Memory usage" buttons {"OK"} default button 1
   
    # write to file
    set someText to number_to_string(vmStats)
   
    set textFile to "/Lanli/RD/Projects/Processing/memory_test/free_mem.txt"
    do shell script "echo  " & quoted form of someText & " >  " & quoted form of textFile

   
   
    return input
end run


# A sub-routine that converts numeric values to strings
on number_to_string(this_number)
    set this_number to this_number as string
    if this_number contains "E+" then
        set x to the offset of "." in this_number
        set y to the offset of "+" in this_number
        set z to the offset of "E" in this_number
        set the decimal_adjust to characters (y - (length of this_number)) thru ¬
            -1 of this_number as string as number
        if x is not 0 then
            set the first_part to characters 1 thru (x - 1) of this_number as string
        else
            set the first_part to ""
        end if
        set the second_part to characters (x + 1) thru (z - 1) of this_number as string
        set the converted_number to the first_part
        repeat with i from 1 to the decimal_adjust
            try
                set the converted_number to ¬
                    the converted_number & character i of the second_part
            on error
                set the converted_number to the converted_number & "0"
            end try
        end repeat
        return the converted_number
    else
        return this_number
    end if
end number_to_string


    6. 檔案 > 儲存: 
        /Lanli/RD/Projects/Processing/memory_test/free_mem.app

-----------------------------------------------------------------------------------------------

B. 開啟 Processing 撰寫程式如下:
import java.util.Date;

String words1;
String words2;
String words3;
String words4;

long allocated;
long free;
long maximum;
long checkTimer;

String[] config;
float free_mem;

void setup() {
  frameRate(15);
  size(400, 400);
  textSize(24);
 
  words1 = "";
  words2 = "";
  words3 = "";
  words4 = "";
 
  checkTimer = (new Date()).getTime();

  //  File[] roots = File.listRoots();
  //
  //  // For each filesystem root, print some info 
  //  for (File root : roots) {
  //    println("File system root: " + root.getAbsolutePath());
  //    println("Total space (bytes): " + root.getTotalSpace());
  //    println("Free space (bytes): " + root.getFreeSpace());
  //    println("Usable space (bytes): " + root.getUsableSpace());
  //  }

}

void draw() {
  background(0);

  if ((new Date()).getTime() - checkTimer >= 2000) {
    checkTimer = (new Date()).getTime();

    open("/Lanli/RD/Projects/Processing/memory_test/free_mem.app");
    //delay(250);
    config = loadStrings("free_mem.txt"); 
    free_mem = float(config[0]) / 1024 / 1024; 

    // The amount of memory allocated so far (usually the -Xms setting)
    allocated = Runtime.getRuntime().totalMemory() / 1024 /1024;

    // Free memory out of the amount allocated (value above minus used)
    free = Runtime.getRuntime().freeMemory() / 1024 /1024;

    // The maximum amount of memory that can eventually be consumed
    // by this application. This is the value set by the Preferences
    // dialog box to increase the memory settings for an application.

    maximum = Runtime.getRuntime().maxMemory() / 1024 / 1024; 

    words1 = "app allocated = "+ allocated + " MB";
    words2 = "app free = "+ free + " MB";
    words3 = "app maximum = "+ maximum + " MB";
    words4 = "sys free_mem = "+ free_mem + " MB";
  }

  text(words1, 10, 25, 540, 300);
  text(words2, 10, 125, 540, 300);
  text(words3, 10, 225, 540, 300);
  text(words4, 10, 325, 540, 300);

  System.gc();
}

-----------------------------------------------------------------------------------------------

C. 執行結果:
       備註: 實體記憶體 (8.00 GB) - 記憶體用量 (2.45 GB) - 快取(2.59 GB)
                 = 2.96 GB 接近 3015.1016 MB / 1024 = 2.944 GB

2015年6月7日 星期日

Processing: Play Ableton Live 9 With LiveOSC and oscP5

since: 2015/06/07
update: 2015/06/07

reference:
1. Andreas Schlegel - oscP5
2. LiveOSC 
3. LiveOSC Processing Bridge

A. 在 Ableton Live 上設置 LiveOSC:
     1. 下載 LiveOSC, 檔名: trunk_LiveOSC-141.zip 解壓縮後的 trunk 資料夾下
         有一個 LiveOSC 的資料夾. (其內的 OSCAPI.txt 可看)

     2. 應用程式 > Ableton Live 9 Suite.app > 顯示套件內容:

     3. 將 LiveOSC 資料夾複製到: Contents > App-Resources > MIDI Remote Scripts 下:

     4. 開啟 Ableton Live:
         a. Live > Preferences... > MIDI Sync > Control Surface: LiveOSC
         > 設定好後, 請先關閉 Live, 再重新開啟.

         b. 新增 Live Set , 編輯完成後存檔.

-----------------------------------------------------------------------------------------------

B. Processing:

     1. 開啟 Processing, 新增 Sketch, 程式碼可完全取自: LiveOSC Processing Bridge

     2. 執行後如下:

2015年6月3日 星期三

Processing: Play GarageBand With Virtual MIDI Cables(Ports) On Mac

since: 2015/06/03
update: 2015/06/03

reference:
1. How to use the IAC Driver - MFA Lab
2. Create virtual MIDI ports on Mac


A. Create a virtual MIDI Port:

    1. 應用程式 > 工具程式 > 音訊 MIDI 設定.app

    2. 視窗 > 顯示 MIDI 錄音室

    3. 滑鼠雙擊 IAC (Inter-application communication) 驅動程式:

    4. 勾選: 裝置已接上電腦; 新增自訂名稱的傳輸埠, 即完成.

-----------------------------------------------------------------------------------------------

B. GarageBand:

    1. 打開 GarageBand, 點選電子樂, 按下 "選擇"

    2. 檢查 "偏好設定": (預設即可)

    3. 選擇合適的演奏樂器, 檔案 > 儲存

-----------------------------------------------------------------------------------------------

C. Processing:
     1. 打開 Processing, 新增 Sketch , 並匯入 MidiBus 函式庫:

     2. 撰寫程式碼如下:
import themidibus.*; //Import the library

MidiBus myBus; // The MidiBus

int channel;
int pitch;
int velocity;

int number;
int value;

void setup() {
  size(400, 400);
  background(0);

  // List all available Midi devices on STDOUT.
  // This will show each device's index and name.

  MidiBus.list();
 
  // Create a new MidiBus with no input device and the "IAC_MIDI" as the output device.
  //myBus = new MidiBus(this, -1, 2);
  myBus = new MidiBus(this,
"IAC_MIDI", "IAC_MIDI"); // Input, Output device
 

  channel = 0;
  pitch = 64;
  velocity = 127;
 
  number = 0;
  value = 90; 
}

void draw() {

  pitch = int(random(127));
  velocity = int(random(127));

  myBus.sendNoteOn(channel, pitch, velocity); // Send a Midi noteOn
  delay(200);
  myBus.sendNoteOff(channel, pitch, velocity); // Send a Midi nodeOff
 
  myBus.sendControllerChange(channel, number, value); // Send a controllerChange
  delay(2000);
}

void noteOn(int channel, int pitch, int velocity) {
  // Receive a noteOn
  println();
  println("Note On:");
  println("--------");
  println("Channel:"+channel);
  println("Pitch:"+pitch);
  println("Velocity:"+velocity);
}

void noteOff(int channel, int pitch, int velocity) {
  // Receive a noteOff
  println();
  println("Note Off:");
  println("--------");
  println("Channel:"+channel);
  println("Pitch:"+pitch);
  println("Velocity:"+velocity);
}

void controllerChange(int channel, int number, int value) {
  // Receive a controllerChange
  println();
  println("Controller Change:");
  println("--------");
  println("Channel:"+channel);
  println("Number:"+number);
  println("Value:"+value);
}

void delay(int time) {
  int current = millis();
  while (millis () < current+time) Thread.yield();
}

     2. 執行結果: