工作と競馬

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

タグ:リアルタイム信号処理

概要

 Pythonでの録音と再生が同時にできる独自のクラスの作成に関する記事。再生および録音するwavファイルの指定メソッドとデバイス選択メソッドを作った。


背景と目的

 前回、クラスの基本骨格を作った。今回は、再生、録音前の準備に相当するwavファイルの指定とデバイスの選択を行うためのメソッドを作りたい。


詳細

1.デバイスの選択メソッド

 前回作成したgetAvailableDevicesの戻り値はPaDeviceInfo構造体だが、デバイスインデクスでも指定できるようにした。Pythonはメソッドのオーバーロードがないらしいので、自分で変数の型を調べて分岐している。

    def setDevice(self, devInfoOrIndex):
        if isinstance(devInfoOrIndex, int):
            self.__mDeviceInfo = self.__p.get_device_info_by_index(devInfoOrIndex)
        else:
            self.__mDeviceInfo = devInfoOrIndex
        print self.__mDeviceInfo.get("name") + ' device selected' # 選択デバイス名を表示
        
2.再生するwavファイルの指定メソッド

 作成したのは、以下のsetSourceWavメソッド。ファイルパスを指定することで、ファイルをオープンしファイルアクセスできる状態にしている。

    def setSourceWav(self, path):
        try:
            self.__mSourceWav =  wave.open(path, 'r')
        except (NameError, SyntaxError):
            self.__mSourceWav = []
3.録音するファイルの指定メソッド

 作成したメソッドは以下。再生と同様ファイルパスを指定すると、ファイルをオープンするが、こちらは書き込みモードなので、ビット深度、サンプリング周波数、チャンネル数も指定する。それらのパラメータは、クラスのメンバ変数として定義した。ビット深度は、今回は16ビット限定としている。

    def setTargetWav(self, path):
        self.__mTargetWav = wave.open(path, 'w')
        self.__mTargetWav.setsampwidth(self.__BIT / 8)
        self.__mTargetWav.setframerate(self.__mFs)
        self.__mTargetWav.setnchannels(self.__mRecChCount)
4.コンストラクタの変更とgetAvailableDevicesの変更

 前回までに、サンプリング周波数を指定する手段がなかった。同一デバイスを使って再生/録音を行うとすると、サンプリング周波数は同一でなければならないので、コンストラクタで指定してしまうのがよいと考えた。そこで、以下のようにコンストラクタを変更。また、getAvailableDevicesは、インスタンスと直接関係ないので、クラスメソッドとすることにした。

    def __init__(self, recChCount = 0, playChCount = 2, Fs = 44100.0):
        self.__mRecChCount = recChCount
        self.__mPlayChCount = playChCount
        self.__mFs = Fs
        # 使うデバイスを仮設定
        availableDeviceInfo= PlayingRecorder.getAvailableDevices(self.__mRecChCount, self.__mPlayChCount, show = False)
        if availableDeviceInfo.count >= 0:
            self.setDevice(availableDeviceInfo[0]) # とりあえず見つかったものの先頭を設定
        else:
            print "device not found." # デバイスが見つからないことを警告
        return None
5.動作確認

 確認というほどでもないが、以下のスクリプトでちゃんと動作した。

from PlayingRecorder import PlayingRecorder
pr = PlayingRecorder(2, 2, 44100.0)
pr.setDevice(13)
pr.setSourceWav('play.wav')
pr.setTargetWav('rec.wav')

まとめと今後の課題

 wavファイルの指定とデバイスの指定まで行うことができた。次回はいよいよ録音と再生部分にとりかかりたい。

概要

 Pythonでのリアルタイムオーディオ信号処理に関する記事。前回の再生に引き続き、録音ができることを確認した。


背景と目的

 前回、ASIOデバイスを使って再生ができる環境を整備できた。これに引き続き、録音もできるか確認する。


詳細

1.プログラム

 作製したプログラムは以下のとおり。再生の時と異なるのは、

  • wavファイルを書き込みモードで開く
  • callback関数の引数in_dataをwavファイルに書き込む
  • streamをinput = trueで開く

 といったあたり。

import pyaudio
import wave
import time
import numpy

# open wave file
wf = wave.open('song.wav', 'w')
wf.setsampwidth(2) # 16bit
wf.setframerate(44100) # 44.1kHz
wf.setnchannels(2) # stereo

# create pyAudio Object
p = pyaudio.PyAudio()

# input device index
input_device_index = 15

# define callback (2)
def callback(in_data, frame_count, time_info, status):
    wf.writeframes(in_data)
    return (None, pyaudio.paContinue)

# open stream using callback (3)
stream = p.open(format = p.get_format_from_width(wf.getsampwidth()),
                channels = wf.getnchannels(),
                rate = wf.getframerate(),
                input_device_index = input_device_index,
                input = True,
                output = False,
                stream_callback = callback)
                
# start the stream (4)
stream.start_stream()

# wait for stream to finish (5)
time.sleep(3)

# stop stream (6)
stream.stop_stream()
stream.close()

wf.close()
# close PyAudio (7)
p.terminate()
2.確認

 プログラムは、input_device_indexでASIOデバイスを指定し、約3秒間録音を行う。終了後、無事wavファイルができていた。そのファイルの中身を確認したのが、図2.1だ。これを再生すると確かに録音された音声が聞こえた。音が途切れたりもしていないようだ。
 というわけで、ASIOデバイスで録音できた。

録音波形
図2.1 録音された波形


まとめと今後の課題

 無事、録音できることが確認できた。今後は、録音と再生を同時にできるプログラムも作ってみたい。

概要

 Pythonでのリアルタイムオーディオ信号処理に関する記事。手始めとして、ASIOデバイスによる再生ができる環境を整え、無事再生できることを確認した。


背景と目的

 以前環境を整えたオーディオ入出力モジュールpyaudioは、実はASIOデバイスが使えなかった。そこで、今回はASIOデバイスが使えるように環境を整備し、再生できることを確認する。


詳細

1.ASIO対応のpyaudioを入手

 以前の記事でインストールしたpyaudioは、

import pyaudio
pa = pyaudio.PyAudio()
hostApiCount = pa.get_host_api_count()
for i in range(0, hostApiCount)
    print pa.get_host_api_info_by_index(i)

 などと打ってみると、私の環境ではAPI数が1となり、MMEしか検出されなかった。
そこで、ASIO対応させる方法をいろいろ調べたところ、
ASIO SDKを用いてpyaudioをコンパイルしなおす
という方法があることが分かった。しかし、なかなか手順が難しくうまくいかなかった。
もうだめかとあきらめていたのだが、こちらのサイト
他人が作ったASIO対応のpyaudio
見つけることができた。というわけで、これをインストールしてみることにした。

2.ASIOデバイスが検出できるか調べる

 早速、以下のコードを作成し、実行してみた。

# pyaudioをインポート
import pyaudio

# PyAudioクラスのインスタンスを取得
a = pyaudio.PyAudio()

# ホストAPI数
hostAPICount = a.get_host_api_count()
print "Host API Count = " + str(hostAPICount)

# ホストAPIの情報を列挙
for cnt in range(0, hostAPICount):
    print a.get_host_api_info_by_index(cnt)
    
# ASIOデバイスの情報を列挙
asioInfo = a.get_host_api_info_by_type(pyaudio.paASIO)
print "ASIO Device Count = " + str(asioInfo.get("deviceCount"))
for cnt in range(0, asioInfo.get("deviceCount")):
    print a.get_device_info_by_host_api_device_index(asioInfo.get("index"), cnt)

 すると、以下の通り、API数が5になり、MME、DirectSound、ASIO、WASAPI、WDM-KSとおそらく私の環境にあるすべてのAPIが検出されたようだ。そして、ASIOデバイス(私の環境ではUA-25)が無事検出できた!これは使えそうだ。

Host API Count = 5
{'index': 0, 'name': u'MME', 'defaultOutputDevice': 4L, 'type': 2L, 'deviceCount': 6L, 'defaultInputDevice': 1L, 'structVersion': 1L}
{'index': 1, 'name': u'Windows DirectSound', 'defaultOutputDevice': 9L, 'type': 1L, 'deviceCount': 6L, 'defaultInputDevice': 6L, 'structVersion': 1L}
{'index': 2, 'name': u'ASIO', 'defaultOutputDevice': 12L, 'type': 3L, 'deviceCount': 1L, 'defaultInputDevice': 12L, 'structVersion': 1L}
{'index': 3, 'name': u'Windows WASAPI', 'defaultOutputDevice': 13L, 'type': 13L, 'deviceCount': 4L, 'defaultInputDevice': 16L, 'structVersion': 1L}
{'index': 4, 'name': u'Windows WDM-KS', 'defaultOutputDevice': 18L, 'type': 11L, 'deviceCount': 5L, 'defaultInputDevice': 17L, 'structVersion': 1L}
ASIO Device Count = 1
{'defaultSampleRate': 44100.0, 'defaultLowOutputLatency': 0.006530612244897959, 'defaultLowInputLatency': 0.006530612244897959, 'maxInputChannels': 2L, 'structVersion': 2L, 'hostApi': 2L, 'index': 12L, 'defaultHighOutputLatency': 0.2089795918367347, 'maxOutputChannels': 2L, 'name': u'UA-25', 'defaultHighInputLatency': 0.2089795918367347}
3.ASIOデバイスで再生ができるか調べる

 というわけで、以下のコードを作成し、再生させてみたところ、無事目的のデバイスから音が鳴った。
どうやら、ちゃんと使えるようだ。目的達成!
 なお、本コードは、いちおう簡単な信号処理ということでcallback関数でLchの位相を反転させて再生させており、実際に音を聞くと気持ち悪い。が、ちゃんとリアルタイムに処理しながら再生できている証拠でもある。

import pyaudio
import wave
import time
import numpy

# open a wave file
wf = wave.open("song.wav", 'r')
chCount = wf.getnchannels();

# instantiate PyAudio (1)
p = pyaudio.PyAudio()

# device select
output_device_index = 12;

# define callback (2)
def callback(in_data, frame_count, time_info, status):    
    data = wf.readframes(frame_count)
    data2 = numpy.fromstring(data, dtype = int16)
    for i in range(0, len(data2) / chCount):
        data2[i * chCount] = data2[i * chCount] * -1;
    return (data2, pyaudio.paContinue)

# open stream using callback (3)
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                        channels = wf.getnchannels(),
                        output_device_index  = output_device_index,
                        rate = wf.getframerate(),
                        output = True,
                        frames_per_buffer = 1024,
                        stream_callback=callback)

# start the stream (4)
stream.start_stream()

# wait for stream to finish (5)
while stream.is_active():
    time.sleep(0.5)
    key = input('If you want to stop stream, please input 0. > ')
    if key == 0:
        print("Stream is stopped.");
        break;
        
# stop stream (6)
stream.stop_stream()
stream.close()
wf.close()

# close PyAudio (7)
p.terminate()

まとめと今後の課題

 Pythonで、ASIOデバイスによる再生ができる環境が整えられた。今度こそリアルタイムオーディオ信号処理に進んでいきたい。

概要

 C++によるオーディオ信号処理プログラミングに関する記事。前回の続きとして、IIRフィルタのフィルタリング処理をリアルタイムに実行するプログラムを実装した。


背景と目的

 前回は、IIRフィルタのフィルタリング処理を実装できた。今回は、IIRフィルタのフィルタリング処理をリアルタイム実行するプログラムの実装をする。


詳細
1.参考プログラム

 リアルタイム処理は、『信号処理のためのプログラミング入門』(技術評論社)という本の第6章で扱われているオーディオファイルの再生プログラムを参考にする。

2.プログラム実装
2.1 Callback関数

 参考プログラムは、Main関数とCallback関数で構成されており、オーディオデバイスが一定量のデータを再生すると、Callback関数が呼ばれる仕組みになっている。リアルタイムでフィルタ処理をするには、Callback関数内で、再生データにフィルタリングを施してから再生バッファへデータを送ればよい。
 ということで、作成したCallback関数は以下のとおり。ファイルからデータをいったんoutという変数に読み出した後、そのまま再生バッファに送らず、IIRFilterProcess(前回作成)という関数でフィルタ処理をして再生バッファに送っている。

//Callback関数
int patestCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, 
       const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData){
 
 //変数の宣言       
 int ret = 0;
 SNDFILE *fp_read = NULL;
 SF_INFO *sf_info_read =NULL;
 CONSOLEAUDIOINFO *pstConsoleAudioInfo = (CONSOLEAUDIOINFO *)userData; //CONSOLEAUDIOINFO型にキャスト
 sf_count_t count;
 void *out; //読み出しデータを仮で受ける

 //ファイルポインタ,ファイル情報を取得
 fp_read = pstConsoleAudioInfo->fp_read;
 sf_info_read =pstConsoleAudioInfo->sf_info_read;

 if(fp_read){

  //ファイルからデータを読み出す
  out = (float *)malloc(framesPerBuffer * sf_info_read->channels * sizeof(float));
  memset(out, 0, framesPerBuffer * sf_info_read->channels * sizeof(float)); //バッファを確保
  count = sf_read_float(fp_read, (float *)out, framesPerBuffer * sf_info_read->channels); //ファイルから1フレームを読み出しoutに入れる

  //繰り返し再生のための処理
  if((unsigned int)count != framesPerBuffer * sf_info_read->channels){
   sf_seek(fp_read, 0, SEEK_SET); //ファイル終端まで行ったら先頭に戻る
  }

  //読み出したデータにLPFをかける, かけたデータを再生バッファに入れる
  IIRFilterProcess((float *)out, (float *)outputBuffer, framesPerBuffer, sf_info_read->channels);
 }

 free(out); //メモリを開放

 return ret;
}
2.2 Main関数

 Main関数では、IIRフィルタのローパスフィルタ係数を算出するための処理とIIRフィルタの遅延RAMを初期化する処理を追加しておく。以下のとおり、前々回作成したLPF係数算出関数を呼び出している。また、前回作成したIIRFILTERDRAM構造体変数を初期化している。

 //IIRフィルタを作る
 lpf_coef = IIR_2d_LPF(1000, 1 / sqrt(2.0), 44100);
 lpf_dram.x1[0] = 0;
 lpf_dram.x1[1] = 0;
 lpf_dram.y1[0] = 0;
 lpf_dram.y1[1] = 0;
 lpf_dram.x2[0] = 0;
 lpf_dram.x2[1] = 0;
 lpf_dram.y2[0] = 0;
 lpf_dram.y2[1] = 0;
3.動作確認

 まず、プログラムを実行したところ、元の音源よりも高域がカットされた音が聞こえ、LPFがかかっていそうなことがわかった。また、実際にフィルタ特性が正しく出ているかホワイトノイズを再生して確認した結果が図3。目的のfc=1kHz、2次LPFが正しくかかっている。
 以上より、リアルタイムフィルタリング処理が達成できた。

20130326233755
図3 LPFをかけたときのスペクトル


まとめと今後の課題

 リアルタイムフィルタリング処理をするプログラムが実装できた。今後は、さらにいろいろなフィルタ、音響エフェクト処理に挑戦していきたい。

概要

 C++によるオーディオ信号処理プログラミングに関する記事。前回の続きとして、IIRフィルタのフィルタリング処理をする関数を作成した。


背景と目的

 前回は、ローパスフィルタの係数算出までを実装できた。今回は、IIRフィルタのフィルタリング処理をする関数の実装をする。


詳細
1.参考書

 前回同様、『C言語で始める音のプログラミング』(オーム社)第6章がC言語でローパスフィルタをかけるプログラムを扱っているため、これを参考書とした。

2.プログラム実装
2.1 フレーム分割

 リアルタイム処理では、入力データすべてに対し一度にフィルタリング処理する時間はない。そこで、フレーム分割が必要である。しかし、IIRフィルタの場合はフレーム間がうまくつながるように工夫が必要である。具体的には2次IIRフィルタでは前フレームの入出力値末尾2サンプルが現フレームの遅延器初期値になる。そこで、本プログラムでは、末尾2サンプルを保持する構造体IIRFILTERDRAMを定義した。

//前フレームの末尾2サンプルを保持するための構造体を定義
typedef struct
{
 double x1[2], x2[2]; //過去の入力
 double y1[2], y2[2]; //過去の出力
}
IIRFILTERDRAM;

 そして、この型の変数lpf_dramをグローバル変数として宣言し、フレーム間のデータのやり取りを行うことにした。

//IIRFILTERDRAM型の変数を宣言
IIRFILTERDRAM lpf_dram;
2.2 フィルタリング処理

 フレーム分割したフィルタリング処理を実装した関数は以下のとおりである。引数は、入力x、出力y、フレーム長さ、チャンネル数である。
 フィルタリング処理は、ループカウンタnが0,1,2以上で場合わけされる。0,1のときは前フレームの入出力値を参照してyを計算する。また、最後に現フレーム末尾2サンプルの入出力値をlpf_dramに格納している。これが次フレームのn=0,1で参照されることで、フレーム間が正しくつながる。

//IIRフィルタの処理
void IIRFilterProcess(float *x, float *y, int framesPerBuffer, int chcnt){

 int n;
 int ch;

 //n < 2では、lpf_dramを参照する
 for(ch = 0; ch < chcnt; ch++){
  //n = 0
  y[chcnt * 0 + ch] = lpf_coef.a[0] * x[chcnt * 0 + ch] + lpf_coef.a[1] * lpf_dram.x1[ch] + lpf_coef.a[2] * lpf_dram.x2[ch]
                                   + lpf_coef.b[1] * lpf_dram.y1[ch] + lpf_coef.b[2] * lpf_dram.y2[ch];
  //n = 1
  y[chcnt * 1 + ch] = lpf_coef.a[0] * x[chcnt * 1 + ch] + lpf_coef.a[1] * x[ch]          + lpf_coef.a[2] * lpf_dram.x1[ch]
                                   + lpf_coef.b[1] * y[ch]          + lpf_coef.b[2] * lpf_dram.y1[ch];
 }

 //n >= 2
 for(n = 2; n < framesPerBuffer; n++){
  for(ch = 0; ch < chcnt; ch++){
   y[chcnt * n + ch] = lpf_coef.a[0] * x[chcnt * n + ch] + lpf_coef.a[1] * x[chcnt * (n - 1) + ch] + lpf_coef.a[2] * x[chcnt * (n - 2) + ch]
                                    + lpf_coef.b[1] * y[chcnt * (n - 1) + ch] + lpf_coef.b[2] * y[chcnt * (n - 2) + ch];
  }
 }

 //次回フレームのため、フレーム末尾2サンプル分を保存
 for(ch = 0; ch < chcnt; ch++){
  lpf_dram.x1[ch] = x[chcnt * (framesPerBuffer - 1) + ch];
  lpf_dram.y1[ch] = y[chcnt * (framesPerBuffer - 1) + ch];
  lpf_dram.x2[ch] = x[chcnt * (framesPerBuffer - 2) + ch];
  lpf_dram.y2[ch] = y[chcnt * (framesPerBuffer - 2) + ch];
 }

}

まとめと今後の課題

 2次IIRフィルタによるローパスフィルタのフィルタリング処理プログラムを作成できた。次回は、これをリアルタイム処理として実装する。

概要

 C++によるオーディオ信号処理プログラミングに関する記事。リアルタイム処理プログラム作成に向けて、手始めとしてローパスフィルタの係数を算出する部分を実装し、動作確認した。


背景と目的

 前回の(1)では、信号処理に必要な環境構築ができた。そこで、念願のリアルタイム処理に手をつけたいと思う。目標は、『再生中の音にローパスフィルタをかける』とする。今回は、構成要素となるローパスフィルタの係数算出プログラムまでを実装してみたい。


詳細
1.参考書

 今回の内容に取り組むにあたり、『C言語で始める音のプログラミング』(オーム社)第6章がC言語でローパスフィルタをかけるプログラムを扱っているため、これを参考書とした。この本は、非リアルタイム処理を扱っているのだが、C言語で各種信号処理のプログラムを実装する方法が示されており、大変参考になる。

IMG_0800
図1 参考書

2.プログラム作成
2.1 IIRフィルタと係数算出方法

 ローパスフィルタは、図2.1に示す2次IIRフィルタとする。このフィルタは係数が5つあるため、パラメータにあわせて設計する必要がある。設計方法は、有名な双一次変換法を用いる。

20130326190836
図2.1 IIRフィルタ

2.2 プログラム実装

 まず、IIRフィルタは係数が5つあるため、それらを保持する変数をまとめた構造体を用意したほうが、便利だろうと考え、以下のIIRFILTERCOEFを定義した。なお、フィードバック側bは2つあればいいのだが、サブスクリプトをaとbでそろえるためあえて3つ用意している。

//IIRフィルタ係数構造体
typedef struct
{
 double a[3]; //フィードフォワード側係数
 double b[3]; //フィードバック側係数
}
IIRFILTERCOEF;

 そして、係数算出関数を以下のように作成した。引数にカットオフ周波数、共振度、サンプリング周波数を指定することで、双一次変換法で係数を算出し、IIRFILTERCOEF型の戻り値が得られる。

//LPFの係数を設計する関数
IIRFILTERCOEF IIR_2d_LPF(double fc, double Q, double fs){

 //fc ディジタルLPFカットオフ周波数
 //Q  クオリティファクタ
 //fs サンプリング周波数

 //変数
 double p1, p2; //計算用
 double wc;  //カットオフ角周波数
 double fc_a; //アナログLPFカットオフ周波数
 IIRFILTERCOEF coef; //係数

 //周波数プリワーピング
 fc_a = tan(pi * fc / fs) / (2 * pi);
 wc = 2 * pi * fc_a;

 //係数計算
    p1 = 1 + wc / Q + wc * wc;
    p2 = 1 - wc / Q + wc * wc;
    coef.a[0] = (wc * wc) / p1;
    coef.a[1] = 2 * (wc * wc) / p1;
    coef.a[2] = coef.a[0];
    coef.b[0] = 1;
    coef.b[1] = -2 * (wc * wc - 1) / p1;
    coef.b[2] = -p2 / p1;

 return coef;

}
3.動作確認

 作成したプログラムにて、fc=1000Hz、Q=1/√2、fs=44100として係数を算出した。その結果、別途用意してある係数算出プログラムと同一の係数が得られ、正しく動作していることが確認できた。


まとめと今後の課題

 2次IIRフィルタによるローパスフィルタの係数算出プログラムを作成できた。次回は、フィルタリング処理プログラムを作成する。

概要

 C++によるオーディオ信号処理プログラミングに関する記事。手始めに書籍『信号処理のためのプログラミング入門』(技術評論社)を参考とし、C++によるオーディオ信号処理プログラミングの開発環境整備とサンプルプログラムの動作確認を行った。


背景と目的

 私はDTMを趣味としているが、その中では各種音響エフェクトを使用している。それらはリアルタイムにオーディオ信号処理を行いいろいろな音を出力していて非常に興味深く、そのようなオーディオ信号処理を自分も実現してみたいと思った。将来的にはPC上でリアルタイムに信号処理を行い自由に音を出してみたい。そこで、まずオーディオ信号処理の世界に足を踏み入れるため、信号処理に必要な環境構築を行い、簡単なプログラムを作成してみる。


活動の詳細
1.方針

 まず、オーディオ信号処理に必要な開発環境がどのようなものかわからなかったのでWeb上で調べてみたところ、『信号処理のためのプログラミング入門』(技術評論社)という本(図1)がC++でリアルタイムオーディオ信号処理に関する内容を扱っていそうだということがわかった。そこで、この本を購入し、この本の内容にしたがって環境構築を行っていくことにした。

IMG_0599
図1 参考とした書籍

2.環境構築

 環境構築は、参考書籍の第3章、第4章を見ながら行った。この本ではVisual C++ Express Editionを用いてプログラムを作成する方法が書かれており、私の環境にはすでにVisual C++がインストールされていたので、オーディオ信号処理に必要ないくつかのライブラリ、SDKをインストールすることで無事環境が構築できた。

3.サンプルプログラムの作成と動作確認

 環境が構築できたので手始めにサンプルプログラムを作成してみた。サンプルプログラムの内容は参考書籍第5章にあるwavファイルのサンプリング周波数とチャンネル数を表示するプログラムである。(以下参照)
 本に書いてある手順に従いプログラムを作成したところ無事コンパイルされプログラムを実行できた。その結果が図3である。読み込ませたwavファイルのサンプリング周波数、チャンネル数が正しく表示されサンプルプログラムが正しく作成できたことがわかった。

作成したプログラム
※以下のプログラムは参考書籍の内容にしたがって環境構築されていないと動作しません。
// consoleplayer.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"

#include  //printf関数などを使うため
#include  //exit関数などを使うため
#include  //memset関数などを使うため

#include  //libsndfileのヘッダ

//メイン関数
int _tmain(int argc, _TCHAR* argv[])
{

 //変数の定義
 SNDFILE *fp_read = NULL; //オーディオファイルのファイルポインタ
 SF_INFO sf_info_read; //オーディオファイルの基本的な情報を格納する構造体

 //sf_info_readの初期化
 //void* memset( void* dest, int c, size_t count )
 //destからcountバイトのメモリー領域をcで埋めます
 memset(&sf_info_read, 0, sizeof(SF_INFO));

 //ファイルを読み込みモードでオープン
 if(argc != 2){
  exit(1); //コマンドラインからの第一引数が空であった場合は終了
 }
 fp_read = sf_open(argv[1], SFM_READ, &sf_info_read);
 if(!fp_read){
  exit(2); //ファイルが見つからなかったら終了
 }

 //サンプリング周波数とチャンネル数を表示
 printf("samplerate is %d\n", sf_info_read.samplerate);
 printf("channels is %d\n", sf_info_read.channels);

 //CLOSE処理
 if(fp_read){
  sf_close(fp_read);
  fp_read = NULL;
 }

 printf("press any keys...");
 getchar();

 return 0;
}


fsとch
図3 サンプルプログラムの動作確認


まとめと今後の課題

 『信号処理のためのプログラミング入門』(技術評論社)を参考とし、オーディオ信号処理のための環境構築およびサンプルプログラムの動作確認をすることができた。現段階では信号処理はできていないので今後は参考書籍の内容に従い信号処理ができるようにしていく。

このページのトップヘ