1
我需要能够以编程方式读取WAV(或CAF)文件并仅将样本(音频)数据提取为字节数组。什么是最简单/最快捷的方式来做到这一点?如何将WAV/CAF文件的采样数据转换为字节数组?
我需要能够以编程方式读取WAV(或CAF)文件并仅将样本(音频)数据提取为字节数组。什么是最简单/最快捷的方式来做到这一点?如何将WAV/CAF文件的采样数据转换为字节数组?
假设你是iOS和OS X,你想AudioToolbox框架,特别是在AudioFile.h
这些API(或ExtAudioFile.h
如果您需要的音频数据转换为上读取另一种格式。)
例如,
#include <AudioToolbox/AudioFile.h>
...
AudioFileID audioFile;
OSStatus err = AudioFileOpenURL(fileURL, kAudioFileReadPermission, 0, &audioFile);
// get the number of audio data bytes
UInt64 numBytes = 0;
UInt32 dataSize = sizeof(numBytes);
err = AudioFileGetProperty(audioFile, kAudioFilePropertyAudioDataByteCount, &dataSize, &numBytes);
unsigned char *audioBuffer = (unsigned char *)malloc(numBytes);
UInt32 toRead = numBytes;
UInt64 offset = 0;
unsigned char *pBuffer = audioBuffer;
while(true) {
err = AudioFileReadBytes(audioFile, true, offset, &toRead, &pBuffer);
if (kAudioFileEndOfFileError == err) {
// cool, we're at the end of the file
break;
} else if (noErr != err) {
// uh-oh, some error other than eof
break;
}
// advance the next read offset
offset += toRead;
// advance the read buffer's pointer
pBuffer += toRead;
toRead = numBytes - offset;
if (0 == toRead) {
// got to the end of file but no eof err
break;
}
}
// Process audioBuffer ...
free(audioBuffer);
下面是我从Getting NSData out of music file in iPhone偷和更新的ARC
- (NSData *)readSoundFileSamples:(NSString *)filePath
{
// Get raw PCM data from the track
NSURL *assetURL = [NSURL fileURLWithPath:filePath];
NSMutableData *data = [[NSMutableData alloc] init];
const uint32_t sampleRate = 16000; // 16k sample/sec
const uint16_t bitDepth = 16; // 16 bit/sample/channel
const uint16_t channels = 2; // 2 channel/sample (stereo)
NSDictionary *opts = [NSDictionary dictionary];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:assetURL options:opts];
AVAssetReader *reader = [[AVAssetReader alloc] initWithAsset:asset error:NULL];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithFloat:(float)sampleRate], AVSampleRateKey,
[NSNumber numberWithInt:bitDepth], AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
[NSNumber numberWithBool:NO], AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey, nil];
AVAssetReaderTrackOutput *output = [[AVAssetReaderTrackOutput alloc] initWithTrack:[[asset tracks] objectAtIndex:0] outputSettings:settings];
[reader addOutput:output];
[reader startReading];
// read the samples from the asset and append them subsequently
while ([reader status] != AVAssetReaderStatusCompleted) {
CMSampleBufferRef buffer = [output copyNextSampleBuffer];
if (buffer == NULL) continue;
CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(buffer);
size_t size = CMBlockBufferGetDataLength(blockBuffer);
uint8_t *outBytes = malloc(size);
CMBlockBufferCopyDataBytes(blockBuffer, 0, size, outBytes);
CMSampleBufferInvalidate(buffer);
CFRelease(buffer);
[data appendBytes:outBytes length:size];
free(outBytes);
}
return data;
}
如何确定的数据有多少字节availab在文件中?我想在这个大小上定义audioBuffer [],所以我可以在一次调用中提取所有可用的数据。 – MusiGenesis
我通过调用'AudioFileGetProperty'来更新我的示例(未经测试的代码,但它编译),演示了如何查询音频数据字节数。我还添加了一个更接近现实世界的读取循环。 –
谢谢。我结束了使用你的原稿,修改后只是继续阅读4096大小的块,直到它结束。我将这些字节添加到NSMutableData对象,所以不难做到。 – MusiGenesis