1

我有一些原始声音数据想要制作成 AIFF 文件格式。我知道音频数据的细节。我尝试从音频中创建波形,但没有奏效。OS X 确实具有创建标头的功能,但它直接寻址文件,我可能不想这样做(该功能SetupAIFFHeader已弃用且在 64 位代码中不可用)。

4

4 回答 4

2

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;
}
于 2013-03-06T19:02:02.210 回答
0

尽管我讨厌车轮改造,但我怀疑您最好的选择可能是推出自己的 AIFF 保存程序。

AIFF 是在 Amiga 上使用的旧 Electronic Arts EA-IFF 格式的扩展;它是一系列 4 字节标识符(类似于 FOURCC)、块长度和数据有效负载。Wikipedia 文章内容丰富,并提供了指向其他站点的链接,其中包含有关格式的详细信息。

http://en.wikipedia.org/wiki/Audio_Interchange_File_Format

于 2013-01-21T01:11:36.143 回答
0

我能够编写正确的 AIFF 文件。最后一点是我使用 sizeof() 作为结构的大小,其中大小省略了前八个字节。我确实使用了 Apple 已弃用的 AIFF.h 标头来获取结构,而且似乎 QuickTime X 和 7 都没有读取我在其中设置的元数据。

你可以在PlayerPRO的 PlayerPRO 6 分支看到我的工作。它在PPApp_AppDelegate.m函数中调用的文件中-createAIFFDataFromSettings:data:

于 2013-01-26T00:54:02.060 回答
0

CoreAudio下面是一些使用 Apple和AudioToolboxmacOS 框架创建 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 音调。

于 2018-07-25T19:43:24.353 回答