音の鳴るブログ

鳴らないこともある

node.js で音を出す

node.js でも信号処理簡単インターフェイス pico.js が使えるようになりました。 もともとMac版のみ対応していたのだけど、便利なモジュールを教えてもらってクロスプラットフォーム対応できた(MacとUbuntuでしか確認していないけど)。npmでインストールできます。

$ npm install node-pico

ブラウザで音を出すプログラムを書くときに、コードを書いてブラウザに移動して再読み込みしてボタンを押す、みたいなやり方をしていてだるかったのだけど、かなり楽になった。

node-dev はコードが更新されるたびに再起動してくれるので、エディタでコードを修正して保存するたびに自動で再生が始まる。再生が始まると困るときは、 module.exports をコメントアウトする。song.js はブラウザでも使えるようにしておくと後々も楽で良い。

下のコードには書いていないけど、必然的にUIと音源が分離されるのも良いと思う。

$ node-dev main.js
// main.js
var pico = require("node-pico");
var song = require("./song");

if (typeof song === "function") pico.play(song());
// song.js
(function() {
    "use strict";
    
    var f1 = function(t) {
        return Math.sin(t*(0.001+Math.sin(t>>10)))*64;
    };
    var f2 = function(t) {
        return (t>>9)&((t<<5)|(Math.sin(t*1.4142)*3000))+(t>>3);
    };
    
    function oneliner() {
        var t = 0, dt = 8000 / pico.samplerate;
        
        return {
            process: function(L, R) {
                for (var i = 0; i < L.length; i++) {
                    L[i] = (f1(t|0) % 256) / 512;
                    R[i] = (f2(t|0) % 256) / 512;
                    t += dt;
                }
            }
        };
    }
    
    var exports = function() {
        return oneliner();
    };
    
    if (typeof module !== "undefined" && module.exports) {
        module.exports = exports;
    } else {
        window.song = exports;
    }
})();
// browser
$("#play").on("click", function() {
    pico.play(song());
});