Objective C生成(空)WAV文件

时间:2012-05-05 18:18:07

标签: objective-c core-audio

我正在尝试将一些音频数据保存到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);

2 个答案:

答案 0 :(得分: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/

希望这有帮助。

答案 1 :(得分:1)

初始问题中代码中的问题是最后缺少AudioFileClose(mRecordFile);行。

对于那些仍然在不使用第三方库的情况下搜索工作样本的人,这里稍作修改的代码片段:

- (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, @"");
}

P.S。:要减少最终文件大小,请将mChannelsPerFrame从2减少到1 mSampleRate(例如减少到11000)