プログラミング > vDSP >

ヒルベルト変換


ステレオ素材をモノにする場合、ヒルベルト変換というもので片チャンの位相を90度ずらしてやるとバランスが崩れず良いらしいという事で、vDSPのFFTを使ってやってみました。

変換したいオーディオデータを実部にいれて、虚部は0のままにしておきます。FFTして、データのナイキストレート以下のレベルを2倍に(DC成分はそのまま)、ナイキストレート以上を0でクリアして、逆FFTすると虚部に90度位相のずれたオーディオデータが返ってきます。

以下が、その処理をするクラスのサンプルです。とりあえずこのサンプルではただFFTしてるだけなので、実際は窓関数かけてオーバーラップさせる感じですかね。

//
//  Hilbert.h
//

#import <Cocoa/Cocoa.h>
#import <Accelerate/Accelerate.h>

@interface Hilbert : NSObject {
   
    vDSP_Length fftLength;
    vDSP_Length fftSize;
    FFTSetup fftSetup;
}

- (id)initWithLog2n:(NSUInteger)log2n;
- (void)setFFTWithLog2n:(NSInteger)log2n;
- (void)processWithReal:(float *)realPtr imag:(float *)imagPtr;
- (void)fftWithReal:(float *)realPtr
imag:(float *)imagPtr inverse:(BOOL)isInv;

@end


//
//  Hilbert.m
//

#import "Hilbert.h"

@implementation Hilbert

- (id)initWithLog2n:(NSUInteger)log2n
{
    self = [super init];
    if (self != nil) {
        [self setFFTWithLog2n:log2n];
    }
    return self;
}

- (void)setFFTWithLog2n:(NSInteger)log2n
{
    fftSize = 1 << log2n;
    fftLength = log2n;
    if (fftSetup != NULL) destroy_fftsetup(fftSetup);
    fftSetup = create_fftsetup(fftLength, FFT_RADIX2);
}

- (void) dealloc
{
    if (fftSetup != NULL) destroy_fftsetup(fftSetup);
    [super dealloc];
}


- (void)processWithReal:(float *)realPtr imag:(float *)imagPtr
{
    //FFTを行う
    [self fftWithReal:realPtr imag:imagPtr inverse:NO];
   
    //ナイキスト・レート以下を2倍にする
    float tScale = 2.0;
    UInt32 tHalfLength = fftSize / 2;
    for (NSUInteger j = 1; j < tHalfLength; j++) {
        realPtr[j] *= tScale;
        imagPtr[j] *= tScale;
    }
   
    //ナイキストレート以上を0にする
    memset(&(realPtr[tHalfLength]), 0, tHalfLength * sizeof(float));
    memset(&(imagPtr[tHalfLength]), 0, tHalfLength * sizeof(float));
   
    //逆FFTを行う
    [self fftWithReal:realPtr imag:imagPtr inverse:YES];
}

- (void)fftWithReal:(float *)realPtr
imag:(float *)imagPtr inverse:(BOOL)isInv
{
    FFTDirection direction = isInv ? FFT_INVERSE : FFT_FORWARD;
    vDSP_Stride stride = 1;
    COMPLEX_SPLIT splitComplex;
    splitComplex.realp = realPtr;
    splitComplex.imagp = imagPtr;

    fft_zip(fftSetup, &splitComplex, stride, fftLength, direction);

    if (isInv) {
        float tScale = (float)1.0 / fftSize;
        vsmul(splitComplex.realp, 1,
&tScale, splitComplex.realp, 1, fftSize);
        vsmul(splitComplex.imagp, 1,
&tScale, splitComplex.imagp, 1, fftSize);
    }
}

@end

トラックバック(0)

このブログ記事を参照しているブログ一覧: ヒルベルト変換

このブログ記事に対するトラックバックURL: http://objective-audio.jp/oa80/mt-tb.cgi/62

コメントする


画像の中に見える文字を入力してください。