プログラミングの備忘録

プログラムをつくる過程を残すもの

processingの備忘録 -音声-

こんにちは。
今回は「processing で音声を扱ってみよう」です。


かなり間が空きましたが、過去に画像とテキストの生成・読み込みを取り上げています。

processingの備忘録 -png、gifの生成- - プログラミングの備忘録
processingの備忘録 -txt、csvの生成- - プログラミングの備忘録
processingの備忘録 -画像、テキストの読み込み- - プログラミングの備忘録

今回は「ファイルの扱いシリーズ」として、さっくりとですが音声ファイルに手を伸ばしてみます。


目次


ライブラリ

processing における音声の取り扱いには、主に2つのライブラリがあります。
「Sound」(Sound / Libraries / Processing.org) と
「Minim」(https://code.compartmental.net/minim/Overview) です。

せっかくなので、この記事ではどちらも取り上げます。


インポートする際には、

  • Sound
import processing.sound.*;


  • Minim
import ddf.minim.*;


また、言わずもがなですが、なんらかの音声ファイルもしくはマイクが必要になります。
音声ファイルはスケッチフォルダに入れておいてください。


音声ファイルの読み込みと再生

このコードでは「test.mp3」という音声ファイルをスケッチフォルダに入れておく必要があります。


  • Sound
import processing.sound.*;

SoundFile file;

void setup() {
  file = new SoundFile(this, "test.mp3"); // ファイルの読み込み
  file.play(); // 再生
}      

void draw() {
}


  • Minim
import ddf.minim.*;

Minim minim;
AudioPlayer player;

void setup(){
  minim = new Minim(this); // 初期化
  player = minim.loadFile("test.mp3"); // ファイルの読み込み
  player.play(); // 再生
}

void draw(){
}


マイクからの入力

  • Sound

マイクから受け取った音声の音量を、円の大きさで表します。

import processing.sound.*;
AudioIn in;
Amplitude amp;

void setup() {
  size(500, 500);
  stroke(255);

  in = new AudioIn(this); // マイクの音声を受け取る
  //in.play(); // 受け取った音声を再生

  amp = new Amplitude(this);
  amp.input(in); // 受け取った音声の音量
}      

void draw(){
  background(0);
  
  float d = 300 * amp.analyze(); // 音量を円の直径に
  ellipse(width/2, height/2, d, d);
}


  • Minim

マイクから受け取った音声を、波形として画面に図示します。

import ddf.minim.*;
 
Minim minim;
AudioInput in;

void setup(){
  size(500, 500);
  stroke(255);

  minim = new Minim(this);
  in = minim.getLineIn(); // マイクの音声を受け取る
  //in.enableMonitoring(); // 受け取った音声を再生
}

void draw(){
  background(0);

  for(int i = 0; i < in.bufferSize()-1; i++){
    line(i, 100 + 100*in.left.get(i), i+1, 100 + 100*in.left.get(i+1)); // 左マイクの音
    line(i, 400 + 100*in.right.get(i), i+1, 400 + 100*in.right.get(i+1)); // 右マイクの音
  }
}


音の再生

これまでは音声ファイルやマイクからの入力音声を再生していましたが、波形から音を再生することもできます。


  • Sound
import processing.sound.*;

SinOsc sine;

void setup() {
  sine = new SinOsc(this); // サイン波の生成
  sine.freq(500); // 周波数を 500 Hz に
  sine.play(); // 再生
}

void draw() {
}


  • Minm
import ddf.minim.*;
import ddf.minim.signals.*; //波をつくるためのライブラリ

Minim minim;
AudioOutput out;
SineWave sine;

void setup(){
  size(500, 500);
  minim = new Minim(this);

  out = minim.getLineOut();

  sine = new SineWave(500, 0.5, out.sampleRate()); // サイン波の生成
  
  out.addSignal(sine); // 出力
}

void draw(){
  background(0);
  stroke(255);

  for(int i = 0; i < out.bufferSize()-1; i++){
    line(i, 100 + 100*out.left.get(i), i+1, 100 + 100*out.left.get(i+1));
    line(i, 400 + 100*out.left.get(i), i+1, 400 + 100*out.left.get(i+1));
  }
}


サイン波の他、矩形波三角波、のこぎり波などもあります。

また合成波に関しては、sine1sine2 など複数の波を生成させ、それぞれについて play()addSignal() を行えば良いということになります。


おまけ

少し前にフーリエ変換について記事にしました。

processingの備忘録 -離散フーリエ変換- - プログラミングの備忘録
processingの備忘録 -高速フーリエ変換- - プログラミングの備忘録
フーリエ変換を利用して絵を描く - プログラミングの備忘録


フーリエ変換ができるようになったら、音を変換して周波数成分を見てみたくなりますよね?


離散フーリエ変換できたてほやほやの頃にやってみたりしてました。
(ちなみに、音声としては木村わいPの「高音厨音域テスト」を使ってみました。今年8月には10周年バージョンが出てましたね。)

(ライブラリ使うんだったら組み込まれてる FFT() 使えば良くない?というコメントは受け付けていません。)


変換用のシグナルとしてマイクからの入力音声を使えば自分の声などもフーリエ変換できます。

今回はやりませんでしたが、フーリエ変換後のスペクトルからどこかの周波数成分を除いて波形に戻す、という操作で音がどう変わるかなど見てみるのも面白いかと思います。


まとめ

以上、processing で音声を扱えるようになりました。
全体として「Sound」の方が簡単な音声の取り扱いができるような気がします。
が、調べたいと思ったときに「sound」という語が一般的すぎてうまく検索できないなと感じました。

ここに挙げた機能が全てはないので、レファレンスを読みながらいろいろ開拓してみたいですね。
音声ファイルの書き出しについても機会があれば記事にしたいと思います。


最後まで読んでいただいてありがとうございました。また次回。