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