2

我正在尝试将一些音频数据保存到 WAV 文件中——我有通常在 RemoteIO 中使用的音频数据,但我现在正在尝试实现一个函数来保存数据。我知道音频数据是有效的,所以这不是问题——如果我可以得到一个正确长度的空 WAV 文件,我可以稍后用数据填充它。

现在,代码创建了文件,它看起来是正确的字节长度,但显然它的格式不正确,因为 OSX、QuickTime、iTunes 等无法识别它(他们看到文件,无法确定长度,或播放它)

    NSURL * tvarFilename = [savePanel URL];
    NSLog(@"doSaveAs filename = %@",tvarFilename);        

    //try to create an audio file there

    AudioFileID mRecordFile;

    AudioStreamBasicDescription audioFormat;
    audioFormat.mSampleRate         = 44100.00;
    audioFormat.mFormatID           = kAudioFormatLinearPCM;
    audioFormat.mFormatFlags        = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    audioFormat.mFramesPerPacket    = 1;
    audioFormat.mChannelsPerFrame   = 2;
    audioFormat.mBitsPerChannel     = 16;
    audioFormat.mBytesPerPacket     = 4;
    audioFormat.mBytesPerFrame      = 4;



    OSStatus status = AudioFileCreateWithURL((CFURLRef)tvarFilename, kAudioFileWAVEType, &audioFormat, kAudioFileFlags_EraseFile, &mRecordFile);

    int beatsToRecord = 4; //temporary

    int bpm = 120;

    double intervalInSamples = (double) 60 / bpm;
    intervalInSamples *= (double)44100;

    int inNumberFrames = (intervalInSamples * beatsToRecord);

    UInt32 frameBuffer[inNumberFrames];

    int sampleTime = 0;

    UInt32 thisSubBuffer[inNumberFrames];

    for (int i = 0; i < inNumberFrames; i++) { frameBuffer[i] = 0; }

    UInt32 bytesToWrite = inNumberFrames * sizeof(UInt32);
    status = AudioFileWriteBytes(mRecordFile, false, 0, &bytesToWrite, &frameBuffer);
4

2 回答 2

1

WAV 文件非常简单:它只包含一个(通常为 44 字节长)标题部分,然后是原始 PCM 数据。我编写了一个需要记录 WAV 文件的库,我很确定你会明白我是如何完成它的。为了澄清:

/**
 * CD quality: 44100 Hz sample rate, 16 bit per sample, 2 channels (stereo):
**/
struct sprec_wav_header *hdr = sprec_wav_header_from_params(44100, 16, 2);
int filesize = (obtain the filesize somehow here);
/**
 * -8 bytes for the first part of the header, see the WAV specification
**/
hdr->filesize = filesize - 8;
int filedesc = open("/tmp/dummy.wav", O_WRONLY | O_CREAT, 0644);
if (sprec_wav_header_write(filedesc, hdr))
{
    printf("Error writing WAV header!\n");
}
close(filedesc);
free(hdr);

还有我写的图书馆:https ://github.com/H2CO3/libsprec/

希望这可以帮助。

于 2012-05-05T18:51:50.183 回答
1

最初问题中的代码问题最终在缺失AudioFileClose(mRecordFile);行中。

对于那些仍然在不使用 3rd 方库的情况下搜索工作示例的人,这里是稍微修改的代码片段:

- (void)createSilentWAVFileAtURL:(NSURL *)fileURL {
    AudioFileID mRecordFile;

    AudioStreamBasicDescription audioFormat;
    audioFormat.mSampleRate         = 44100.00;
    audioFormat.mFormatID           = kAudioFormatLinearPCM;
    audioFormat.mFormatFlags        = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    audioFormat.mFramesPerPacket    = 1;
    audioFormat.mChannelsPerFrame   = 2;
    audioFormat.mBitsPerChannel     = 16;
    audioFormat.mBytesPerPacket     = 4;
    audioFormat.mBytesPerFrame      = 4;

    OSStatus status = AudioFileCreateWithURL((__bridge CFURLRef)fileURL, kAudioFileWAVEType, &audioFormat, kAudioFileFlags_EraseFile, &mRecordFile);

    double intervalInSamples = 0.5;
    intervalInSamples *= audioFormat.mSampleRate * audioFormat.mChannelsPerFrame;

    int beatsToRecord = 4; //seconds of silence
    int inNumberFrames = (intervalInSamples * beatsToRecord);

    UInt32 frameBuffer[inNumberFrames];

    for (int i = 0; i < inNumberFrames; i++) { frameBuffer[i] = 0; }

    UInt32 bytesToWrite = inNumberFrames * sizeof(uint32_t);
    status = AudioFileWriteBytes(mRecordFile, false, 0, &bytesToWrite, &frameBuffer);
    status = AudioFileClose(mRecordFile);

    NSAssert(status == noErr, @"");
}

PS:要减少最终文件大小mChannelsPerFrame,请从 2 减少到 1 和mSampleRate(例如到 11000)

于 2016-05-16T15:56:58.527 回答