2017年3月20日月曜日

Ubuntu studioでのPortAudio



Ubuntu StudioでPortAudioのコードコンパイル・実行してみました.今まではMacとWindowsでしかやったことなかったのですが,Macでのやり方とほとんど同じでした.

コードはWindowsでやった時と全く同じです.

Linuxでは,PortAudioはALSA-SDKを使います.ですから,ALSA-SDKのインストール -> PortAudioのインストール -> プログラムの開発 という手順になります.


1, ALSA-SDKをインストール

sudo apt-get install libasound-dev

2, PortAudioをダウンロード.適当な場所にコピーして,以下のコマンドで解凍.

tar zxvf pa_stable_v190600_20161030.tgz

3, 以下のコマンドでPortAudioをコンパイル・インストール

./configure && make

sudo make install

4, "/bin/local/lib" にPortAudioの関連ファイルが出来ていれば成功




5, "~/.bashrc" に以下を追加することによってライブラリの環境変数を設定

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

6, 適当なディレクトリを作ってコーディング

7, コンパイル.a.outを実行.

gcc main.c -lm -lportaudio


"-lportaudio"を加えることによってPortAudioが使えます.今回のコードでは,sin関数を使っているため,"-lm"も必要です.

本当に簡単ですね.





2017年3月18日土曜日

MacでのPortAudio【2019/07/22追記】



昨日の投稿で勢いづいたので,MacでのPortAudio v19.06をやってみました.

ソースコードは昨日載せたのと全く同じです.

Xcodeでビルドできるようにします.手順は以下.

【追記】
High SierraあたりのOSから,これまでのやり方ではビルドできなくなっていました.この度,Mojaveでビルドに成功したので,その方法を追記いたします.



1, PortAudioをダウンロード.適当な場所に解凍.

2, ターミナルで"PortAudio"に移動し,以下のコマンドを実行.

./configure && make


【追記】

このコマンドの実行が失敗します.これを回避するために,上記コマンドの代わりに以下のコマンドを実行します.

./configure --disable-mac-universal && make



3, "PortAudio/lib" に各種依存ファイルができている

4, "PortAudio/lib/.libs/" に移動(.libs はFinder からは見えないので,ターミナルで移動して初めて中身が見える)

5, "PortAudio/lib/.libs/" に "libportaudio.a" があることを確認

【追記】

コンパイラがgccの場合は,"libportaudio.a"を利用しますが,最近のXcodeのコンパイラはデフォルトではclangになっています.Xcodeのコンパイラをgccにしない(デフォルトのまま使う)のなら,"libportaudio.a"ではなく,同じディレクトリにある"libportaudio.dylib"を利用します.

6, 今後使いやすいように, "libportaudio.a" を Finderで見えるパスにコピー.

【追記】

コンパイラがclangなら,コピーするのは"libportaudio.dylib"です.

7, Xcodeでプロジェクトを作成,コーディング.

8, 以下のフレームワークをプロジェクトに追加

AudioToolbox.framework
AudioUnit.framework
CoreAudio.framework
CoreServices.framework

【追記】

手順8は不要になりました.

9, "libportaudio.a" をプロジェクトのフォルダにコピー

【追記】

コンパイラがclangなら,コピーするのは"libportaudio.dylib"です.

10, "libportaudio.a" をプロジェクトに追加

【追記】

コンパイラがclangなら,追加するのは"libportaudio.dylib"です.
また,"portaudio/include/portaudio.h"もプロジェクトに追加します.

11, ビルド

【追記】

実行する前に,"portaudio/lib/.libs/libportaudio.2.dylib"を"/usr/local/lib"下にコピーする必要があります.これをしないと,ビルドは成功しても,実行することができません.

以上でできます.1〜6を一回やってしまえば,後は簡単にできます.

【追記】
Mojaveでのビルド


2017年3月17日金曜日

最新のPortAudioを試す

私が音響信号処理に興味を持った頃,パソコンで音の出るプログラム(単にオーディオファイルを再生したりするプログラムのことではなく,DSPなどでよくやるようなリアルタイムに音を入出力して1サンプルごと処理していくようなプログラムのことです)を作るのは,かなり高度なテクニックに入る部類だったように思います.今は簡単になったのかというとそうでもなくて,私自身が色々と知ってしまったのであまり難しいとは感じなくなっただけなのですが,とにかく当時は未知の世界でした.当時,パソコン上で音を扱うプログラムについて解説した本は,日本語のものでは1冊しかありませんでした.その本のサンプルが,やたら長いソースコードで,ものぐさな私にはとてもやる気になれる内容ではありませんでした.(今では数冊この分野の本があります.)

勿論,MATLABやScilabで信号処理をして音を出すことは,当時も簡単にできました.しかし,音楽・音響制作の分野に身を置いていた私は,とにかく,リアルタイム入出力のアプリケーションこそが正義.これができなければ信号処理を勉強している意味がないと思っていました.

そんな中,知人が「最近使い始めた」と教えてくれたのがPortAudioでした.

http://www.portaudio.com/

PortAudioは,オープンソースのオーディオ入出力APIで,以下の点が特徴です.

・オーディオの基本的な機能を使うソースコードが簡単になる

・既存のオーディオAPIの抽象化として存在する

・クロス・プラットフォームである

クロス・プラットフォームというのはかなり魅力的で,現在のバージョンでは以下に対応しています.

・Windows DirectSound
・Windows WASAPI
・ASIO
・Mac CoreAudio
・UNIX OSS/ALSA

OS依存のAPIを同時に使ったりしない限り,これらの扱いが,全く同じソースコードでできてしまいます.

歴史はかなり古く,コンピュータ音楽の作曲家・技術者の間ではお馴染みのICMCで,2001年に発表されています.


http://www.portaudio.com/docs/portaudio_icmc2001.pdf

調べれば調べるほど,多くの音関係のオープンソースプロジェクトがPortAudioを使っていることが分かります.

私は,これまでずっとv18.1を使ってきました.理由は,上記の知人もそのバージョンを使っていたのと,まだプログラミングに完全に慣れきっていなかった私にもしっくりくる書き方ができたからです.しかし,v18.1のリリースは2003年.さすがに古すぎます.(ことさらに古さを演出するために,ここで「2003年といえば,〇〇があった年ですよ」とか書こうと思い,2003年の出来事を調べたが,あまり古いと感じる出来事がなかったので書くのをやめた)

そこで最新バージョンv19.06を使ってみることにしました.使ってみると,私の知っているPortAudioとは少し勝手が違っていたので,ビルド方法を紹介します.ゆとり世代なので,初めから統合開発環境Visual Studioを使います.先ほど紹介したPortAudioの特徴の恩恵に預かることが目的なので,PortAudioそのものの深い詮索等はせずに,一旦音の出るアプリケーションがビルドできればOKとします.

対象とするオーディオ環境はDirectSound.ビルドまでの手順が一番簡単だからです.

1, 上記webからPortAudioをダウンロード,解凍して "portaudio" フォルダを適当な場所にコピー.

2, ASIO SDKをダウンロード(今現在の最新バージョンは 2.3)

https://www.steinberg.net/en/company/developers.html

3, 解凍した "ASIOSDK2.3" フォルダを "portaudio/src/hostapi/asio/" にコピー.更に, "ASIOSDK2.3" -> "ASIOSDK" にリネーム.

4, "portaudio/build/msvc/portaudio.vcproj"をVisual Studioで開く(この時,比較的新しいVisual Studioを使うと,プロジェクトが最新化の環境に合わせて変換される)

5, ビルド設定を好みの設定にしてビルド.(今回はx86 Releaseにした)

6, 成功すると,"portaudio/build/msvc/Win32/Release"(Win32以下はビルド設定によって変わる) に "portaudio_x86.lib" "portaudio_x86.dll" が出来ている.

7, 新しいプロジェクト(空のプロジェクト)を作って,PortAudioを使ったコードをコーディング.

8, "portaudio/include/" をインクルードパスに設定して同ディレクトリの "portaudio.h" "pa_win_ds.h" をプロジェクトに追加する.

9, "portaudio/build/msvc/Win32/Release" をリンカのライブラリパスに設定して,同ディレクトリの "portaudio_x86.lib","winmm.lib"と"dsound.lib"をライブラリに追加する.

10, ビルド."portaudio_x86.dll" をアプリケーションと同じディレクトリにコピーすれば動作する.

という流れになります.v18.1と違うのは,"portaudio_〇〇.lib" "portaudio_〇〇.dll" をビルドしないといけない点です.v18.1では,各オーディオ環境に応じたインクルードファイルとソースファイルを追加してビルドする方式でしたが,現在のバージョンでは,Windowsベースのオーディオ環境(恐らくDirectSoundとWASAPIとASIO)はlibとdllにまとめられていて,それをリンクすれば全ての環境が使えるようになるみたいです.例えば,同じアプリケーションで複数のオーディオ環境をサポートするようなアプリケーションは,これで作りやすくなったと言えますが,個人的には,事前準備なくソースを追加するだけで音を出せるv18.1の方が楽なので好きです.

さて,ソースコードですが,例えば,正弦波を出すようなアプリケーションは以下のコードで出来ます.特にちゃんとやる必要性がある訳ではないので,エラー処理を完全に省略しましたが,それにしても本当に簡単です.


#include<stdio.h>
#include<math.h>
#include"portaudio.h"
#define Fs 44100 //サンプリング周波数
#define FRAMES_PER_BUFFER 128 //バッファサイズ
#define pi 3.14159265358979323

/*ユーザ定義データ*/
typedef struct{
    float freq; //正弦波の周波数
    float index;
}padata;

/* オーディオ処理コールバック関数*/
static int dsp(const void *inputBuffer, //入力
               void *outputBuffer, //出力
               unsigned long framesPerBuffer,
               const PaStreamCallbackTimeInfo *timeInfo,
               PaStreamCallbackFlags statusFlags,
               void *userData //ユーザ定義データ 
               ){
    padata *data = (padata *)userData;
    float *out = (float *)outputBuffer;
    long i;

    for( i=0; i<framesPerBuffer; i++){
        *out++ = 0.7 * sin( 2 * pi * data->freq * data->index / Fs ); //チャンネル1(左)
        *out++ = 0.7 * sin( 2 * pi * data->freq * data->index / Fs ); //チャンネル2(右)
        data->index+=1.f;
    }
    return 0;
}
int main(void){
    PaStreamParameters outParam; //出力の定義
    PaStream *stream;
    PaError err;
    padata data; //ユーザ定義データ
    data.freq = 800.f;
    data.index = 0.f;

    //PortAudio初期化
    Pa_Initialize();

    //出力の設定
    outParam.device = Pa_GetDefaultOutputDevice(); //デフォルトのオーディオデバイス
    outParam.channelCount = 2;
    outParam.sampleFormat = paFloat32; //32bit floatで処理
    outParam.suggestedLatency = Pa_GetDeviceInfo( outParam.device )->defaultLowOutputLatency;
    outParam.hostApiSpecificStreamInfo = NULL;

    //PortAudioオープン
    Pa_OpenStream(
        &stream,
        NULL,
        &outParam,
        Fs,
        FRAMES_PER_BUFFER,
        paClipOff,
        dsp,
        &data);
    
    //PortAudioスタート
    Pa_StartStream(stream);

    //エンターキーが押されるまで待機
    getchar();

    //PortAudio終了
    Pa_StopStream(stream);
    Pa_CloseStream(stream);
    Pa_Terminate();
    return 0;
}


入力を使いたいときは,同じように PaStreamParameters を入力用に定義して,PaOpenStreamの引数にすればよいです.


2017年3月10日金曜日

GoldWave

この記事を読んでいる中で,音に携わる方は,波形編集ソフトは何を使っているでしょうか?いわゆるDAWとよばれるProToolsやCubase,Nuendo等は除外すると,フリーでは

・Audacity
・SoundEngine Free
・wavosaur

等があり,有料のものでは

・WaveLab
・SoundForge

等が有名で使っている人をよく見かけます.

今日は,あまり使っている人を見かけない,でもかなり面白い波形編集ソフト「GoldWave」を紹介します.

https://www.goldwave.com/

GoldWaveはシェアウェアで,当面使う分には無料ですが,継続的に使うには45ドルを払う必要があります.

画面はこんな感じ.


左側のウィンドウに波形,右側のウィンドウにはオーディオのリアルタイム解析結果が表示されます.色々な表示モードがあります.





基本的に普通の波形編集ソフトで出来ることは一通り出来ると思っていてよいです.エフェクトも色々あります.DirectXプラグインを追加することも出来るみたいです.(やったことありません.)



このソフトのエフェクトの特徴として,とにかくどぎつくエフェクトをかけられるということが言えます.例えば,フィルタを使ってみると,こんな急峻なフィルタも設定できてしまいます.






他のエフェクトもかなり極端な使い方が出来るので,音をラディカルにいじりたい人にはもってこいです.

しかし,GoldWaveの本当の特徴は,どぎついエフェクタではありません.
Toolメニューの中に "Expression Evaluator" という項目があります.



Expression Evaluator


Expression Evaluator(直訳:数式評価器)





そう,オーディオデータに対して数式ベースの処理が出来るのです.これが出来る波形編集ソフトを他に知りません.(知ってる方は教えてください.便利そうだったらそちらに乗り換えます.)

それでは,ちょっとやってみましょう.

まず,"New"で空のオーディオデータを作ります.今回はfs=44100Hzの一秒間のデータを作りました.


そして,Expression Evaluatorを開いて,正弦波を作ってみます.GoldWaveのsin関数は2πで1周期となるので,周波数f(Hz)のnサンプル目の値は

y(n)=sin(2 * π * f * n / fs)

となります.GoldWaveではサンプリング周波数は定数Nとして定義されているので,以下のように書けばよいです.

sin(2*pi*f*n/N)


fの値はウィンドウ下部のテキストボックスに入力します.面倒なら,変数を使わずに

sin(2*pi*500*n/N)

と書いても良いでしょう.(というより,私はいつもそうしてる.)

これで,OKを押すと,最初に作ったオーディオデータに,今入力した数式の値が出力されます.見事な正弦波です.



ちなみに,上記式の "n/N" は,同じ値が変数 "t" として定義されています.つまり,上記式は,こう書いたのと等価です.

sin(2*pi*f*t)

お好みと用途に応じて使い分けましょう.

この要領で色々な波形を作れます.

・のこぎり波(アンチ・エイリアシングなし)

※ int()は多くのプログラミング言語で言うところのfloor()です.




・矩形波(アンチ・エイリアシングなし)




最後に,オーディオ入出力の例として2次のIIRフィルタを実装してみましょう.ディジタルフィルタの知識のない方は,関連図書を読んでからまたここへ戻ってきてください.

どんなフィルタにするかですが,ナイキスト周波数の半分のところがカットオフ周波数になるバタワース特性のフィルタにしましょう.手前味噌で恐縮ですが,MATLABで係数を求めてしまいましょう.



まず,空のオーディオデータを作って,ホワイトノイズを作ります.一様乱数の関数randを使えばよいです.




今作ったオーディオデータが入力.出力用のオーディオデータ(空)を作ります.今までと同じやり方です.


上が今作った出力用のオーディオデータです.では,Expression Evaluatorを開きます.


Expression Evaluatorでは,現在GoldWaveで扱っているオーディオデータのサンプルをwave1(n), wave2(n) ・・・というような配列で扱います.どれがどのデータなのかということは, "Source" というところのコンボボックスで確認できます.今回の場合,入力がwave2,出力がwave1ですね.そして,今回のように扱うオーディオデータが複数ある場合,"Destination"で正しく出力先を選ぶ必要があります.今回は, "Untitled7"をDestinationにします.

さて,先ほどMATLABで求めた係数を使って,IIRフィルタの式を記述します.面倒なので係数0の項は省略しました.



"OK" を押すと,"Untitled7" にフィルタの出力が書き込まれました.ちゃんとローパスフィルタになっていますね.

フィードバックの係数を大きくすると,カットオフ周波数付近でピークが出来る様子が観察できます.



こんな面白い機能のある波形編集ソフト「GoldWave」.なかなか使っている人に出会わないのですが,面白い音を作りたい方,音と数式で遊びたい方なんかにはうってつけのソフトではないかと思います.

初めてのブログ投稿.画像がとんでもなく多くなってしまいました.一記事あたりの画像数の相場ってどれくらいなんでしょうね?

2017年3月9日木曜日

試しに投稿

日々あまり深く考えずに適当に実装していることなどをまとめます.

音響・映像技術の研究開発を行っています.

元々音楽が専門で,舞台やレコーディングのサウンドエンジニアリング等を行っていましたが,色々あって理系に鞍替えしました.大学院では音響信号処理と聴覚の研究をして,現在は持ち前の適当さを生かして適当な映像システムを作っては,営業やクライアントをヒヤヒヤさせるのが仕事です.やっぱりお金は大事なのでサラリーマンとして働いてはいますが,本当は研究がしたい.ドクター入学が夢です.

上記の他にも,コンピュータシミュレーション(主に天文シミュレーション)や複雑系科学に興味があります.(興味があるのと,詳しくて習熟しているのとは違います.)

恐らくキーワードになるであろう語群:
C++ MATLAB Max vvvv OpenCV Cuda OpenCL OpenGL シンセサイザ エフェクタ


後は,音楽の話題もちょいちょい挟みたい.