2012-05-05 40 views
2

我試圖將一些音頻數據保存到WAV文件 - 我有我通常在RemoteIO中使用過的音頻數據,但我現在試圖實現一個函數保存數據。我知道音頻數據是有效的,所以這不是一個問題 - 如果我只能得到一個正確長度的空WAV文件,我可以在稍後填入數據。Objective C生成(空)WAV文件

現在,代碼創建文件,它看起來是正確的字節長度,但顯然它沒有正確格式化,因爲OSX,QuickTime,iTunes等無法識別它(他們看到文件,可以「T確定的長度,或播放)

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); 
+1

您應該使用十六進制編輯器檢查文件,並查看它們與標準的不同之處。 –

+0

是的 - 我認爲這是我的下一步。現在潛入它 –

+0

好吧,看起來問題是標題 - 其餘數據正在被正確寫入。 所以,換句話說,AudioFileCreateWithURL()調用是什麼導致的主要問題,它看起來像 –

回答

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/

希望這有助於。

+0

謝謝 - 我已經開始掃描您的代碼。但是,必須有一種方法可以用AudioFileWriteBytes來做到這一點,對吧?這不就是爲了什麼功能嗎? –

+0

AudioFile API只有在想要認真地將其集成到AudioUnits,AudioQueues等,以便使用較低級別的CoreAudio API時才真正有用。如果你只是想創建一個空的WAV文件,它真的不值得。就像你自己說的那樣,你以後可以用最適合你的方法填寫它。 – 2012-05-05 21:33:46

+0

你是什麼意思不值得?看起來好像,如果我剔除任何不正確的參數,我將有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, @""); 
} 

PS:爲了降低最終文件大小從2減少mChannelsPerFrame 1和mSampleRate(例如,爲了11000)