如何播放和读取.caf PCMaudio文件
我有一个应用程序,从iPod库中select一首歌曲,然后将该歌曲作为“.caf”文件复制到应用程序的目录中。 我现在需要播放,同时从Accelerate框架将该文件读入Apples FFT,这样我就可以像声谱图一样可视化数据。 这里是FFT的代码:
void FFTAccelerate::doFFTReal(float samples[], float amp[], int numSamples) { int i; vDSP_Length log2n = log2f(numSamples); //Convert float array of reals samples to COMPLEX_SPLIT array A vDSP_ctoz((COMPLEX*)samples,2,&A,1,numSamples/2); //Perform FFT using fftSetup and A //Results are returned in A vDSP_fft_zrip(fftSetup, &A, 1, log2n, FFT_FORWARD); //Convert COMPLEX_SPLIT A result to float array to be returned amp[0] = A.realp[0]/(numSamples*2); for(i=1;i<numSamples;i++) amp[i]=sqrt(A.realp[i]*A.realp[i]+A.imagp[i]*A.imagp[i])/numSamples; } //Constructor FFTAccelerate::FFTAccelerate (int numSamples) { vDSP_Length log2n = log2f(numSamples); fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2); int nOver2 = numSamples/2; A.realp = (float *) malloc(nOver2*sizeof(float)); A.imagp = (float *) malloc(nOver2*sizeof(float)); }
我的问题是如何循环“.caf”audio文件来提供FFT,同时播放歌曲? 我只需要一个频道 我猜我需要得到歌曲的1024个样本,在FTT中处理,然后再向下移动文件,再抓取1024个样本。 但我不明白如何读取audio文件来做到这一点。 该文件有44100.0赫兹的采样率,是线性PCM格式,16位,我相信也是交错,如果有帮助…
尝试ExtendedAudioFile API(需要AudioToolbox.framework)。
#include <AudioToolbox/ExtendedAudioFile.h> NSURL *urlToCAF = ...; ExtAudioFileRef caf; OSStatus status; status = ExtAudioFileOpenURL((__bridge CFURLRef)urlToCAF, &caf); if(noErr == status) { // request float format const UInt32 NumFrames = 1024; const int ChannelsPerFrame = 1; // Mono, 2 for Stereo // request float format AudioStreamBasicDescription clientFormat; clientFormat.mChannelsPerFrame = ChannelsPerFrame; clientFormat.mSampleRate = 44100; clientFormat.mFormatID = kAudioFormatLinearPCM; clientFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved; // float int cmpSize = sizeof(float); int frameSize = cmpSize*ChannelsPerFrame; clientFormat.mBitsPerChannel = cmpSize*8; clientFormat.mBytesPerPacket = frameSize; clientFormat.mFramesPerPacket = 1; clientFormat.mBytesPerFrame = frameSize; status = ExtAudioFileSetProperty(caf, kExtAudioFileProperty_ClientDataFormat, sizeof(clientFormat), &clientFormat); if(noErr != status) { /* handle it */ } while(1) { float buf[ChannelsPerFrame*NumFrames]; AudioBuffer ab = { ChannelsPerFrame, sizeof(buf), buf }; AudioBufferList abl; abl.mNumberBuffers = 1; abl.mBuffers[0] = ab; UInt32 ioNumFrames = NumFrames; status = ExtAudioFileRead(caf, &ioNumFrames, &abl); if(noErr == status) { // process ioNumFrames here in buf if(0 == ioNumFrames) { // EOF! break; } else if(ioNumFrames < NumFrames) { // TODO: pad buf with zeroes out to NumFrames } else { float amp[NumFrames]; // scratch space doFFTReal(buf, amp, NumFrames); } } } // later status = ExtAudioFileDispose(caf); if(noErr != status) { /* hmm */ } }