AIFF ファイル形式にしたい生のサウンド データがいくつかあります。音声データの詳細を知っています。オーディオからウェーブを作成しようとしましたが、うまくいきませんでした。OS X にはヘッダーを作成する関数がありますが、ファイルを直接アドレス指定するので、私はそうしたくないかもしれません (それと関数SetupAIFFHeader
は非推奨であり、64 ビット コードでは使用できません)。
4 に答える
Apple の Core Audio API は、データを作成して AIFF ファイルやその他の形式に書き込みます。それはかなりうまく機能しますが、私の意見では、API は使いにくいです。以下にコード例をいくつか貼り付けますが、おそらく変更したいと思うでしょう。AudioFileWriteBytes
一度に 2 バイト以上書き込むことができます。別のラッパー API がありAudioToolbox/ExtendedAudioFile.h
、32 ビット浮動小数点のような形式を記述して、それを AIFF/PCM または圧縮形式の基になる形式に変換できます。
double sampleRate = 44100;
double duration = ...;
long nSamples = (long)(sampleRate * duration);
// Format struct for 1 channel, 16 bit PCM audio
AudioStreamBasicDescription asbd;
memset(&asbd, 0, sizeof(asbd));
asbd.mSampleRate = sampleRate;
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger;
asbd.mBitsPerChannel = 16;
asbd.mChannelsPerFrame = 1;
asbd.mFramesPerPacket = 1;
asbd.mBytesPerFrame = 2;
asbd.mBytesPerPacket = 2;
CFURLRef url = makeUrl("hello.aiff");
AudioFileID audioFile;
OSStatus res;
res = AudioFileCreateWithURL(url, kAudioFileAIFFType, &asbd,
kAudioFileFlags_EraseFile, &audioFile);
checkError(res);
UInt32 numBytes = 2;
for (int i=0; i<nSamples; i++) {
SInt16 sample = ... // something between SHRT_MIN and SHRT_MAX;
sample = OSSwapHostToBigInt16(sample);
res = AudioFileWriteBytes(audioFile, false, i*2, &numBytes, &sample);
checkError(res);
}
res = AudioFileClose(audioFile);
checkError(res);
checkError
res == noErr と主張しています。makeUrl
次のようになります。
CFURLRef makeUrl(const char *cstr) {
CFStringRef path = CFStringCreateWithCString(0, cstr, kCFStringEncodingUTF8);
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, 0, false);
CFRelease(path);
return url;
}
適切な AIFF ファイルを書き込むことができました。最後に気になったのは、構造体のサイズに sizeof() を使用していたことです。このサイズでは、最初の 8 バイトが省略されています。Apple の非推奨の AIFF.h ヘッダーを使用して構造を取得しましたが、設定したメタデータを QuickTime X も 7 も読み取っていないようです。
私の作品はPlayerPROの PlayerPRO 6 ブランチで見ることができます。PPApp_AppDelegate.m
関数で呼び出されるファイルにあります-createAIFFDataFromSettings:data:
私は車輪の再発明が嫌いですが、あなたの最善の策は、独自の AIFF 保存ルーチンをロールバックすることではないかと思います。
AIFF は、Amiga で使用されていた古い Electronic Arts EA-IFF フォーマットの拡張です。これは、一連の 4 バイトの識別子 (FOURCC に類似)、ブロック長、およびデータ ペイロードです。ウィキペディアの記事は非常に有益であり、形式に関する詳細情報を含む他のサイトへのリンクを提供しています。
CoreAudio
AppleとAudioToolbox
macOSのフレームワークを使用して AIFF ファイルを作成する C コードを次に示します。
#include <string.h>
#include <math.h>
#include "CoreAudio/CoreAudio.h"
#include "CoreAudio/CoreAudioTypes.h"
#include "AudioToolbox/AudioToolbox.h"
#include "AudioToolbox/AudioFile.h"
CFURLRef MakeUrl(const char *cstr);
void CheckError(OSStatus res);
AudioStreamBasicDescription asbd;
AudioFileID audioFile;
OSStatus res;
void CheckError(OSStatus result) {
if (result == noErr) return;
switch(result) {
case kAudioFileUnspecifiedError:
printf("kAudioFileUnspecifiedError");
break;
case kAudioFileUnsupportedFileTypeError:
printf("kAudioFileUnsupportedFileTypeError");
break;
case kAudioFileUnsupportedDataFormatError:
printf("kAudioFileUnsupportedDataFormatError");
break;
case kAudioFileUnsupportedPropertyError:
printf("kAudioFileUnsupportedPropertyError");
break;
case kAudioFileBadPropertySizeError:
printf("kAudioFileBadPropertySizeError");
break;
case kAudioFilePermissionsError:
printf("kAudioFilePermissionsError");
break;
case kAudioFileNotOptimizedError:
printf("kAudioFileNotOptimizedError");
break;
case kAudioFileInvalidChunkError:
printf("kAudioFileInvalidChunkError");
break;
case kAudioFileDoesNotAllow64BitDataSizeError:
printf("kAudioFileDoesNotAllow64BitDataSizeError");
break;
case kAudioFileInvalidPacketOffsetError:
printf("kAudioFileInvalidPacketOffsetError");
break;
case kAudioFileInvalidFileError:
printf("kAudioFileInvalidFileError");
break;
case kAudioFileOperationNotSupportedError:
printf("kAudioFileOperationNotSupportedError");
break;
case kAudioFileNotOpenError:
printf("kAudioFileNotOpenError");
break;
case kAudioFileEndOfFileError:
printf("kAudioFileEndOfFileError");
break;
case kAudioFilePositionError:
printf("kAudioFilePositionError");
break;
case kAudioFileFileNotFoundError:
printf("kAudioFileFileNotFoundError");
break;
default:
printf("unknown error");
break;
}
exit(result);
}
CFURLRef MakeUrl(const char *cstr) {
CFStringRef path = CFStringCreateWithCString(0, cstr, kCFStringEncodingUTF8);
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, 0, false);
CFRelease(path);
return url;
}
int main() {
double sampleRate = 44100.0;
double duration = 10.0;
long nSamples = (long)(sampleRate * duration);
memset(&asbd, 0, sizeof(asbd));
// Format struct for 1 channel, 16 bit PCM audio
asbd.mSampleRate = sampleRate;
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger;
asbd.mBitsPerChannel = 16;
asbd.mChannelsPerFrame = 1;
asbd.mFramesPerPacket = 1;
asbd.mBytesPerFrame = 2;
asbd.mBytesPerPacket = 2;
CFURLRef url = MakeUrl("sinpos.aiff");
res = AudioFileCreateWithURL(url, kAudioFileAIFFType, &asbd,
kAudioFileFlags_EraseFile, &audioFile);
CheckError(res);
UInt32 numBytes = 2;
int freq = 44; // 100 for approx 440Hz, 2940 for 15Hz, 44 for 1000Hz
for (int i=0; i<nSamples; i++) {
int x = (i % freq);
double angle = 2.0*3.1459*x/freq;
double s = 1.0*32767*sin(angle);
SInt16 sample = (SInt16) s;
sample = OSSwapHostToBigInt16(sample);
res = AudioFileWriteBytes(audioFile, false, i*2, &numBytes, &sample);
CheckError(res);
}
res = AudioFileClose(audioFile);
CheckError(res);
exit(0);
}
は次のMakefile
とおりです。
aiffcreate: aiffcreate.c
gcc -o $@ $< -framework AudioToolbox -framework CoreFoundation -framework CoreAudio -lm
clean:
rm *.aiff aiffcreate || true
./aiffcreate
これは、コマンドラインでコマンドを発行するだけで実行でき、sinpos.aiff
10 秒間持続する純粋な 1000Hz トーンであるという名前のファイルが作成されます。