24ビット

Pocket

24bitのオーディオデータを作ったり読みこもうとしてもObjective-C(というかC言語)では24bitの型がありませんので、符号付き32bit整数の上位24bit分を使うというのが簡単な方法ではないかと思います。

ただこの場合、32bitの下位8bitは単純に切り捨てられますので、音にこだわるのであればディザをかけたりしたほうが良いのかもしれませんが、とりあえず今回は無視します。

32bit領域のAlignedHighなデータとして渡したりするのであれば何もしなくてもいいですが、32bit領域でAlignedLowな24bitのデータにしなくちゃいけないなんて時があったりしたら、

SInt32 value;

という、あるオーディオのデータがあったとして、

value >>= 8;

としてやります。

処理系によって算術シフトになるか論理シフトが変わるらしいですが、Xcodeでgccを使っているのであればこの場合算術シフトで、valueがマイナスのときは上位8bitが1で埋め尽くされています。

ちなみに、IntelMac想定の検証コード。

#import <Foundation/Foundation.h>

void logBit (SInt32 value) {
    printf("MSB ");
    for (NSInteger i = 3; i >= 0; i--) {
        Byte *valuePtr = (Byte *)&value;
        for (NSInteger j = 7; j >= 0; j--) {
            SInt32 isBitOn = (valuePtr[i] & (1 << j)) ? YES : NO;
            printf("%d", isBitOn);
        }
        printf(" ");
    }
    printf(" LSB\n\n");
}

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    SInt32 value = INT32_MIN;
    printf("value = %d\n", value);
    logBit(value);
    
    SInt32 sValue = value;
    sValue >>= 8;
    printf("signed shift value = %d\n", sValue);
    logBit(sValue);
    
    UInt32 uValue = (UInt32)value;
    uValue >>= 8;
    printf("unsigned shift value = %u\n", uValue);
    logBit(uValue);
    
    [pool drain];
    return 0;
}

実行すると…

value = -2147483648
MSB 10000000 00000000 00000000 00000000  LSB

signed shift value = -8388608
MSB 11111111 10000000 00000000 00000000  LSB

unsigned shift value = 8388608
MSB 00000000 10000000 00000000 00000000  LSB

という感じになります。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です